keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 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 "GL2Encoder.h" |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 18 | #include "GLESv2Validation.h" |
| 19 | |
| 20 | #include <string> |
| 21 | #include <map> |
| 22 | |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 23 | #include <assert.h> |
| 24 | #include <ctype.h> |
| 25 | |
Lingfeng Yang | 6906660 | 2016-04-12 09:29:11 -0700 | [diff] [blame] | 26 | #include <GLES2/gl2.h> |
| 27 | #include <GLES2/gl2ext.h> |
| 28 | #include <GLES2/gl2platform.h> |
| 29 | |
| 30 | #include <GLES3/gl3.h> |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 31 | #include <GLES3/gl31.h> |
Lingfeng Yang | 6906660 | 2016-04-12 09:29:11 -0700 | [diff] [blame] | 32 | |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 33 | #ifndef MIN |
| 34 | #define MIN(a, b) ((a) < (b) ? (a) : (b)) |
| 35 | #endif |
| 36 | |
| 37 | static GLubyte *gVendorString= (GLubyte *) "Android"; |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 38 | static GLubyte *gRendererString= (GLubyte *) "Android HW-GLES 3.0"; |
| 39 | static GLubyte *gVersionString= (GLubyte *) "OpenGL ES 3.0"; |
Nicolas Capens | fe2d51a | 2015-11-20 15:10:09 -0500 | [diff] [blame] | 40 | static GLubyte *gExtensionsString= (GLubyte *) "GL_OES_EGL_image_external "; |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 41 | |
Lingfeng Yang | 0728990 | 2017-01-27 12:26:19 -0800 | [diff] [blame] | 42 | #define SET_ERROR_IF(condition, err) if((condition)) { \ |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 43 | ALOGE("%s:%s:%d GL error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \ |
Lingfeng Yang | 0728990 | 2017-01-27 12:26:19 -0800 | [diff] [blame] | 44 | ctx->setError(err); \ |
| 45 | return; \ |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 46 | } |
| 47 | |
Lingfeng Yang | 0728990 | 2017-01-27 12:26:19 -0800 | [diff] [blame] | 48 | #define SET_ERROR_WITH_MESSAGE_IF(condition, err, generator, genargs) if ((condition)) { \ |
| 49 | std::string msg = generator genargs; \ |
| 50 | ALOGE("%s:%s:%d GL error 0x%x\n" \ |
| 51 | "Info: %s\n", __FILE__, __FUNCTION__, __LINE__, err, msg.c_str()); \ |
| 52 | ctx->setError(err); \ |
| 53 | return; \ |
| 54 | } \ |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 55 | |
Lingfeng Yang | 0728990 | 2017-01-27 12:26:19 -0800 | [diff] [blame] | 56 | #define RET_AND_SET_ERROR_IF(condition, err, ret) if((condition)) { \ |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 57 | ALOGE("%s:%s:%d GL error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \ |
Lingfeng Yang | 0728990 | 2017-01-27 12:26:19 -0800 | [diff] [blame] | 58 | ctx->setError(err); \ |
| 59 | return ret; \ |
| 60 | } \ |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 61 | |
Lingfeng Yang | 0728990 | 2017-01-27 12:26:19 -0800 | [diff] [blame] | 62 | #define RET_AND_SET_ERROR_WITH_MESSAGE_IF(condition, err, ret, generator, genargs) if((condition)) { \ |
| 63 | std::string msg = generator genargs; \ |
| 64 | ALOGE("%s:%s:%d GL error 0x%x\n" \ |
| 65 | "Info: %s\n", __FILE__, __FUNCTION__, __LINE__, err, msg.c_str()); \ |
| 66 | ctx->setError(err); \ |
| 67 | return ret; \ |
| 68 | } \ |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 69 | |
Yahan Zhou | b7f0908 | 2016-03-10 11:45:02 -0800 | [diff] [blame] | 70 | GL2Encoder::GL2Encoder(IOStream *stream, ChecksumCalculator *protocol) |
| 71 | : gl2_encoder_context_t(stream, protocol) |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 72 | { |
Lingfeng Yang | e6556dc | 2017-01-09 12:04:12 -0800 | [diff] [blame] | 73 | m_currMajorVersion = 2; |
| 74 | m_currMinorVersion = 0; |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 75 | m_initialized = false; |
Lingfeng Yang | e980c7a | 2018-01-12 14:50:18 -0800 | [diff] [blame] | 76 | m_noHostError = false; |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 77 | m_state = NULL; |
| 78 | m_error = GL_NO_ERROR; |
| 79 | m_num_compressedTextureFormats = 0; |
Lizhe Liu | e41f4ef | 2015-05-27 11:13:23 +0800 | [diff] [blame] | 80 | m_max_cubeMapTextureSize = 0; |
| 81 | m_max_renderBufferSize = 0; |
| 82 | m_max_textureSize = 0; |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 83 | m_max_3d_textureSize = 0; |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 84 | m_max_vertexAttribStride = 0; |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 85 | m_compressedTextureFormats = NULL; |
David 'Digit' Turner | 3afd44b | 2014-10-30 18:15:04 +0100 | [diff] [blame] | 86 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 87 | m_ssbo_offset_align = 0; |
| 88 | m_ubo_offset_align = 0; |
| 89 | |
Lingfeng Yang | de51dfb | 2016-10-17 22:48:59 -0700 | [diff] [blame] | 90 | m_drawCallFlushCount = 0; |
| 91 | m_primitiveRestartEnabled = false; |
| 92 | m_primitiveRestartIndex = 0; |
| 93 | |
Lingfeng Yang | 0728990 | 2017-01-27 12:26:19 -0800 | [diff] [blame] | 94 | // overrides |
David 'Digit' Turner | 3afd44b | 2014-10-30 18:15:04 +0100 | [diff] [blame] | 95 | #define OVERRIDE(name) m_##name##_enc = this-> name ; this-> name = &s_##name |
Lingfeng Yang | e6556dc | 2017-01-09 12:04:12 -0800 | [diff] [blame] | 96 | #define OVERRIDE_CUSTOM(name) this-> name = &s_##name |
| 97 | #define OVERRIDEWITH(name, target) do { \ |
| 98 | m_##target##_enc = this-> target; \ |
| 99 | this-> target = &s_##name; \ |
| 100 | } while(0) |
| 101 | #define OVERRIDEOES(name) OVERRIDEWITH(name, name##OES) |
bohu | 56bf82f | 2014-10-17 15:35:48 -0700 | [diff] [blame] | 102 | |
David 'Digit' Turner | 3afd44b | 2014-10-30 18:15:04 +0100 | [diff] [blame] | 103 | OVERRIDE(glFlush); |
| 104 | OVERRIDE(glPixelStorei); |
| 105 | OVERRIDE(glGetString); |
| 106 | OVERRIDE(glBindBuffer); |
| 107 | OVERRIDE(glBufferData); |
| 108 | OVERRIDE(glBufferSubData); |
| 109 | OVERRIDE(glDeleteBuffers); |
| 110 | OVERRIDE(glDrawArrays); |
| 111 | OVERRIDE(glDrawElements); |
| 112 | OVERRIDE(glGetIntegerv); |
| 113 | OVERRIDE(glGetFloatv); |
| 114 | OVERRIDE(glGetBooleanv); |
| 115 | OVERRIDE(glVertexAttribPointer); |
| 116 | OVERRIDE(glEnableVertexAttribArray); |
| 117 | OVERRIDE(glDisableVertexAttribArray); |
| 118 | OVERRIDE(glGetVertexAttribiv); |
| 119 | OVERRIDE(glGetVertexAttribfv); |
| 120 | OVERRIDE(glGetVertexAttribPointerv); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 121 | |
Bo Hu | 73568cd | 2015-01-20 16:29:50 -0800 | [diff] [blame] | 122 | this->glShaderBinary = &s_glShaderBinary; |
David 'Digit' Turner | 3afd44b | 2014-10-30 18:15:04 +0100 | [diff] [blame] | 123 | this->glShaderSource = &s_glShaderSource; |
| 124 | this->glFinish = &s_glFinish; |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 125 | |
David 'Digit' Turner | 3afd44b | 2014-10-30 18:15:04 +0100 | [diff] [blame] | 126 | OVERRIDE(glGetError); |
| 127 | OVERRIDE(glLinkProgram); |
| 128 | OVERRIDE(glDeleteProgram); |
| 129 | OVERRIDE(glGetUniformiv); |
| 130 | OVERRIDE(glGetUniformfv); |
| 131 | OVERRIDE(glCreateProgram); |
| 132 | OVERRIDE(glCreateShader); |
| 133 | OVERRIDE(glDeleteShader); |
| 134 | OVERRIDE(glAttachShader); |
| 135 | OVERRIDE(glDetachShader); |
| 136 | OVERRIDE(glGetAttachedShaders); |
| 137 | OVERRIDE(glGetShaderSource); |
| 138 | OVERRIDE(glGetShaderInfoLog); |
| 139 | OVERRIDE(glGetProgramInfoLog); |
| 140 | |
| 141 | OVERRIDE(glGetUniformLocation); |
| 142 | OVERRIDE(glUseProgram); |
| 143 | |
| 144 | OVERRIDE(glUniform1f); |
| 145 | OVERRIDE(glUniform1fv); |
| 146 | OVERRIDE(glUniform1i); |
| 147 | OVERRIDE(glUniform1iv); |
| 148 | OVERRIDE(glUniform2f); |
| 149 | OVERRIDE(glUniform2fv); |
| 150 | OVERRIDE(glUniform2i); |
| 151 | OVERRIDE(glUniform2iv); |
| 152 | OVERRIDE(glUniform3f); |
| 153 | OVERRIDE(glUniform3fv); |
| 154 | OVERRIDE(glUniform3i); |
| 155 | OVERRIDE(glUniform3iv); |
| 156 | OVERRIDE(glUniform4f); |
| 157 | OVERRIDE(glUniform4fv); |
| 158 | OVERRIDE(glUniform4i); |
| 159 | OVERRIDE(glUniform4iv); |
| 160 | OVERRIDE(glUniformMatrix2fv); |
| 161 | OVERRIDE(glUniformMatrix3fv); |
| 162 | OVERRIDE(glUniformMatrix4fv); |
| 163 | |
| 164 | OVERRIDE(glActiveTexture); |
| 165 | OVERRIDE(glBindTexture); |
| 166 | OVERRIDE(glDeleteTextures); |
| 167 | OVERRIDE(glGetTexParameterfv); |
| 168 | OVERRIDE(glGetTexParameteriv); |
| 169 | OVERRIDE(glTexParameterf); |
| 170 | OVERRIDE(glTexParameterfv); |
| 171 | OVERRIDE(glTexParameteri); |
| 172 | OVERRIDE(glTexParameteriv); |
bohu | 26a9298 | 2014-11-25 16:50:37 -0800 | [diff] [blame] | 173 | OVERRIDE(glTexImage2D); |
Yahan Zhou | 2a20829 | 2016-06-22 15:36:04 -0700 | [diff] [blame] | 174 | OVERRIDE(glTexSubImage2D); |
Lingfeng Yang | e00ec9d | 2016-09-16 08:54:03 -0700 | [diff] [blame] | 175 | OVERRIDE(glCopyTexImage2D); |
Lingfeng Yang | 57cb41b | 2016-04-08 14:42:34 -0700 | [diff] [blame] | 176 | |
| 177 | OVERRIDE(glGenRenderbuffers); |
| 178 | OVERRIDE(glDeleteRenderbuffers); |
| 179 | OVERRIDE(glBindRenderbuffer); |
Lingfeng Yang | 6906660 | 2016-04-12 09:29:11 -0700 | [diff] [blame] | 180 | OVERRIDE(glRenderbufferStorage); |
Lingfeng Yang | 57cb41b | 2016-04-08 14:42:34 -0700 | [diff] [blame] | 181 | OVERRIDE(glFramebufferRenderbuffer); |
| 182 | |
| 183 | OVERRIDE(glGenFramebuffers); |
| 184 | OVERRIDE(glDeleteFramebuffers); |
| 185 | OVERRIDE(glBindFramebuffer); |
| 186 | OVERRIDE(glFramebufferTexture2D); |
| 187 | OVERRIDE(glFramebufferTexture3DOES); |
| 188 | OVERRIDE(glGetFramebufferAttachmentParameteriv); |
Lingfeng Yang | 6906660 | 2016-04-12 09:29:11 -0700 | [diff] [blame] | 189 | |
| 190 | OVERRIDE(glCheckFramebufferStatus); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 191 | |
| 192 | OVERRIDE(glGenVertexArrays); |
| 193 | OVERRIDE(glDeleteVertexArrays); |
| 194 | OVERRIDE(glBindVertexArray); |
| 195 | OVERRIDEOES(glGenVertexArrays); |
| 196 | OVERRIDEOES(glDeleteVertexArrays); |
| 197 | OVERRIDEOES(glBindVertexArray); |
| 198 | |
Lingfeng Yang | fb3d2bb | 2017-09-07 15:02:04 -0700 | [diff] [blame] | 199 | OVERRIDE_CUSTOM(glMapBufferOES); |
| 200 | OVERRIDE_CUSTOM(glUnmapBufferOES); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 201 | OVERRIDE_CUSTOM(glMapBufferRange); |
| 202 | OVERRIDE_CUSTOM(glUnmapBuffer); |
| 203 | OVERRIDE_CUSTOM(glFlushMappedBufferRange); |
| 204 | |
| 205 | OVERRIDE(glCompressedTexImage2D); |
| 206 | OVERRIDE(glCompressedTexSubImage2D); |
| 207 | |
| 208 | OVERRIDE(glBindBufferRange); |
| 209 | OVERRIDE(glBindBufferBase); |
| 210 | |
| 211 | OVERRIDE(glCopyBufferSubData); |
| 212 | |
| 213 | OVERRIDE(glGetBufferParameteriv); |
| 214 | OVERRIDE(glGetBufferParameteri64v); |
| 215 | OVERRIDE(glGetBufferPointerv); |
| 216 | |
| 217 | OVERRIDE_CUSTOM(glGetUniformIndices); |
| 218 | |
| 219 | OVERRIDE(glUniform1ui); |
| 220 | OVERRIDE(glUniform2ui); |
| 221 | OVERRIDE(glUniform3ui); |
| 222 | OVERRIDE(glUniform4ui); |
| 223 | OVERRIDE(glUniform1uiv); |
| 224 | OVERRIDE(glUniform2uiv); |
| 225 | OVERRIDE(glUniform3uiv); |
| 226 | OVERRIDE(glUniform4uiv); |
| 227 | OVERRIDE(glUniformMatrix2x3fv); |
| 228 | OVERRIDE(glUniformMatrix3x2fv); |
| 229 | OVERRIDE(glUniformMatrix2x4fv); |
| 230 | OVERRIDE(glUniformMatrix4x2fv); |
| 231 | OVERRIDE(glUniformMatrix3x4fv); |
| 232 | OVERRIDE(glUniformMatrix4x3fv); |
| 233 | |
| 234 | OVERRIDE(glGetUniformuiv); |
| 235 | OVERRIDE(glGetActiveUniformBlockiv); |
| 236 | |
| 237 | OVERRIDE(glGetVertexAttribIiv); |
| 238 | OVERRIDE(glGetVertexAttribIuiv); |
| 239 | |
| 240 | OVERRIDE_CUSTOM(glVertexAttribIPointer); |
| 241 | |
| 242 | OVERRIDE(glVertexAttribDivisor); |
| 243 | |
| 244 | OVERRIDE(glRenderbufferStorageMultisample); |
| 245 | OVERRIDE(glDrawBuffers); |
| 246 | OVERRIDE(glReadBuffer); |
| 247 | OVERRIDE(glFramebufferTextureLayer); |
| 248 | OVERRIDE(glTexStorage2D); |
| 249 | |
| 250 | OVERRIDE_CUSTOM(glTransformFeedbackVaryings); |
| 251 | OVERRIDE(glBeginTransformFeedback); |
| 252 | OVERRIDE(glEndTransformFeedback); |
| 253 | OVERRIDE(glPauseTransformFeedback); |
| 254 | OVERRIDE(glResumeTransformFeedback); |
| 255 | |
| 256 | OVERRIDE(glTexImage3D); |
| 257 | OVERRIDE(glTexSubImage3D); |
| 258 | OVERRIDE(glTexStorage3D); |
| 259 | OVERRIDE(glCompressedTexImage3D); |
| 260 | OVERRIDE(glCompressedTexSubImage3D); |
| 261 | |
| 262 | OVERRIDE(glDrawArraysInstanced); |
| 263 | OVERRIDE_CUSTOM(glDrawElementsInstanced); |
| 264 | OVERRIDE_CUSTOM(glDrawRangeElements); |
| 265 | |
| 266 | OVERRIDE_CUSTOM(glGetStringi); |
| 267 | OVERRIDE(glGetProgramBinary); |
| 268 | OVERRIDE(glReadPixels); |
| 269 | |
| 270 | OVERRIDE(glEnable); |
| 271 | OVERRIDE(glDisable); |
| 272 | OVERRIDE(glClearBufferiv); |
| 273 | OVERRIDE(glClearBufferuiv); |
| 274 | OVERRIDE(glClearBufferfv); |
| 275 | OVERRIDE(glBlitFramebuffer); |
| 276 | OVERRIDE_CUSTOM(glGetInternalformativ); |
| 277 | |
| 278 | OVERRIDE(glGenerateMipmap); |
| 279 | |
| 280 | OVERRIDE(glBindSampler); |
| 281 | |
Lingfeng Yang | f000ab4 | 2017-01-11 18:31:38 -0800 | [diff] [blame] | 282 | OVERRIDE_CUSTOM(glFenceSync); |
| 283 | OVERRIDE_CUSTOM(glClientWaitSync); |
| 284 | OVERRIDE_CUSTOM(glWaitSync); |
| 285 | OVERRIDE_CUSTOM(glDeleteSync); |
| 286 | OVERRIDE_CUSTOM(glIsSync); |
| 287 | OVERRIDE_CUSTOM(glGetSynciv); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 288 | |
| 289 | OVERRIDE(glGetIntegeri_v); |
| 290 | OVERRIDE(glGetInteger64i_v); |
Lingfeng Yang | 80a3633 | 2017-07-09 10:58:07 -0700 | [diff] [blame] | 291 | OVERRIDE(glGetInteger64v); |
| 292 | OVERRIDE(glGetBooleani_v); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 293 | |
| 294 | OVERRIDE(glGetShaderiv); |
| 295 | |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 296 | OVERRIDE(glActiveShaderProgram); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 297 | OVERRIDE_CUSTOM(glCreateShaderProgramv); |
| 298 | OVERRIDE(glProgramUniform1f); |
| 299 | OVERRIDE(glProgramUniform1fv); |
| 300 | OVERRIDE(glProgramUniform1i); |
| 301 | OVERRIDE(glProgramUniform1iv); |
| 302 | OVERRIDE(glProgramUniform1ui); |
| 303 | OVERRIDE(glProgramUniform1uiv); |
| 304 | OVERRIDE(glProgramUniform2f); |
| 305 | OVERRIDE(glProgramUniform2fv); |
| 306 | OVERRIDE(glProgramUniform2i); |
| 307 | OVERRIDE(glProgramUniform2iv); |
| 308 | OVERRIDE(glProgramUniform2ui); |
| 309 | OVERRIDE(glProgramUniform2uiv); |
| 310 | OVERRIDE(glProgramUniform3f); |
| 311 | OVERRIDE(glProgramUniform3fv); |
| 312 | OVERRIDE(glProgramUniform3i); |
| 313 | OVERRIDE(glProgramUniform3iv); |
| 314 | OVERRIDE(glProgramUniform3ui); |
| 315 | OVERRIDE(glProgramUniform3uiv); |
| 316 | OVERRIDE(glProgramUniform4f); |
| 317 | OVERRIDE(glProgramUniform4fv); |
| 318 | OVERRIDE(glProgramUniform4i); |
| 319 | OVERRIDE(glProgramUniform4iv); |
| 320 | OVERRIDE(glProgramUniform4ui); |
| 321 | OVERRIDE(glProgramUniform4uiv); |
| 322 | OVERRIDE(glProgramUniformMatrix2fv); |
| 323 | OVERRIDE(glProgramUniformMatrix2x3fv); |
| 324 | OVERRIDE(glProgramUniformMatrix2x4fv); |
| 325 | OVERRIDE(glProgramUniformMatrix3fv); |
| 326 | OVERRIDE(glProgramUniformMatrix3x2fv); |
| 327 | OVERRIDE(glProgramUniformMatrix3x4fv); |
| 328 | OVERRIDE(glProgramUniformMatrix4fv); |
| 329 | OVERRIDE(glProgramUniformMatrix4x2fv); |
| 330 | OVERRIDE(glProgramUniformMatrix4x3fv); |
| 331 | |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 332 | OVERRIDE(glProgramParameteri); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 333 | OVERRIDE(glUseProgramStages); |
| 334 | OVERRIDE(glBindProgramPipeline); |
| 335 | |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 336 | OVERRIDE(glGetProgramResourceiv); |
| 337 | OVERRIDE(glGetProgramResourceIndex); |
| 338 | OVERRIDE(glGetProgramResourceLocation); |
| 339 | OVERRIDE(glGetProgramResourceName); |
| 340 | OVERRIDE(glGetProgramPipelineInfoLog); |
| 341 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 342 | OVERRIDE(glVertexAttribFormat); |
| 343 | OVERRIDE(glVertexAttribIFormat); |
| 344 | OVERRIDE(glVertexBindingDivisor); |
| 345 | OVERRIDE(glVertexAttribBinding); |
| 346 | OVERRIDE(glBindVertexBuffer); |
| 347 | |
| 348 | OVERRIDE_CUSTOM(glDrawArraysIndirect); |
| 349 | OVERRIDE_CUSTOM(glDrawElementsIndirect); |
| 350 | |
| 351 | OVERRIDE(glTexStorage2DMultisample); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 352 | } |
| 353 | |
| 354 | GL2Encoder::~GL2Encoder() |
| 355 | { |
| 356 | delete m_compressedTextureFormats; |
| 357 | } |
| 358 | |
| 359 | GLenum GL2Encoder::s_glGetError(void * self) |
| 360 | { |
| 361 | GL2Encoder *ctx = (GL2Encoder *)self; |
| 362 | GLenum err = ctx->getError(); |
| 363 | if(err != GL_NO_ERROR) { |
Lingfeng Yang | 80a3633 | 2017-07-09 10:58:07 -0700 | [diff] [blame] | 364 | ctx->m_glGetError_enc(ctx); // also clear host error |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 365 | ctx->setError(GL_NO_ERROR); |
| 366 | return err; |
| 367 | } |
| 368 | |
Lingfeng Yang | e980c7a | 2018-01-12 14:50:18 -0800 | [diff] [blame] | 369 | if (ctx->m_noHostError) { |
| 370 | return GL_NO_ERROR; |
| 371 | } else { |
| 372 | return ctx->m_glGetError_enc(self); |
| 373 | } |
Lingfeng Yang | 80a3633 | 2017-07-09 10:58:07 -0700 | [diff] [blame] | 374 | } |
Yahan Zhou | ae30fe8 | 2016-08-10 21:15:45 +0000 | [diff] [blame] | 375 | |
Lingfeng Yang | 80a3633 | 2017-07-09 10:58:07 -0700 | [diff] [blame] | 376 | class GL2Encoder::ErrorUpdater { |
| 377 | public: |
| 378 | ErrorUpdater(GL2Encoder* ctx) : |
| 379 | mCtx(ctx), |
| 380 | guest_error(ctx->getError()), |
| 381 | host_error(ctx->m_glGetError_enc(ctx)) { |
| 382 | // Preserve any existing GL error in the guest: |
| 383 | // OpenGL ES 3.0.5 spec: |
| 384 | // The command enum GetError( void ); is used to obtain error information. |
| 385 | // Each detectable error is assigned a numeric code. When an error is |
| 386 | // detected, a flag is set and the code is recorded. Further errors, if |
| 387 | // they occur, do not affect this recorded code. When GetError is called, |
| 388 | // the code is returned and the flag is cleared, so that a further error |
| 389 | // will again record its code. If a call to GetError returns NO_ERROR, then |
| 390 | // there has been no detectable error since the last call to GetError (or |
| 391 | // since the GL was initialized). |
| 392 | if (guest_error == GL_NO_ERROR) { |
| 393 | guest_error = host_error; |
| 394 | } |
| 395 | } |
| 396 | |
| 397 | GLenum getHostErrorAndUpdate() { |
| 398 | host_error = mCtx->m_glGetError_enc(mCtx); |
| 399 | if (guest_error == GL_NO_ERROR) { |
| 400 | guest_error = host_error; |
| 401 | } |
| 402 | return host_error; |
| 403 | } |
| 404 | |
| 405 | void updateGuestErrorState() { |
| 406 | mCtx->setError(guest_error); |
| 407 | } |
| 408 | |
| 409 | private: |
| 410 | GL2Encoder* mCtx; |
| 411 | GLenum guest_error; |
| 412 | GLenum host_error; |
| 413 | }; |
| 414 | |
| 415 | template<class T> |
| 416 | class GL2Encoder::ScopedQueryUpdate { |
| 417 | public: |
| 418 | ScopedQueryUpdate(GL2Encoder* ctx, uint32_t bytes, T* target) : |
| 419 | mCtx(ctx), |
| 420 | mBuf(bytes, 0), |
| 421 | mTarget(target), |
| 422 | mErrorUpdater(ctx) { |
| 423 | } |
| 424 | T* hostStagingBuffer() { |
| 425 | return (T*)&mBuf[0]; |
| 426 | } |
| 427 | ~ScopedQueryUpdate() { |
| 428 | GLint hostError = mErrorUpdater.getHostErrorAndUpdate(); |
Lingfeng Yang | 72ecf47 | 2018-06-11 14:20:14 -0700 | [diff] [blame^] | 429 | if (hostError == GL_NO_ERROR && mTarget) { |
Lingfeng Yang | 80a3633 | 2017-07-09 10:58:07 -0700 | [diff] [blame] | 430 | memcpy(mTarget, &mBuf[0], mBuf.size()); |
| 431 | } |
| 432 | mErrorUpdater.updateGuestErrorState(); |
| 433 | } |
| 434 | private: |
| 435 | GL2Encoder* mCtx; |
| 436 | std::vector<char> mBuf; |
| 437 | T* mTarget; |
| 438 | ErrorUpdater mErrorUpdater; |
| 439 | }; |
| 440 | |
| 441 | void GL2Encoder::safe_glGetBooleanv(GLenum param, GLboolean* val) { |
| 442 | ScopedQueryUpdate<GLboolean> query(this, glUtilsParamSize(param) * sizeof(GLboolean), val); |
| 443 | m_glGetBooleanv_enc(this, param, query.hostStagingBuffer()); |
| 444 | } |
| 445 | |
| 446 | void GL2Encoder::safe_glGetFloatv(GLenum param, GLfloat* val) { |
| 447 | ScopedQueryUpdate<GLfloat> query(this, glUtilsParamSize(param) * sizeof(GLfloat), val); |
| 448 | m_glGetFloatv_enc(this, param, query.hostStagingBuffer()); |
| 449 | } |
| 450 | |
| 451 | void GL2Encoder::safe_glGetIntegerv(GLenum param, GLint* val) { |
| 452 | ScopedQueryUpdate<GLint> query(this, glUtilsParamSize(param) * sizeof(GLint), val); |
| 453 | m_glGetIntegerv_enc(this, param, query.hostStagingBuffer()); |
| 454 | } |
| 455 | |
| 456 | void GL2Encoder::safe_glGetInteger64v(GLenum param, GLint64* val) { |
| 457 | ScopedQueryUpdate<GLint64> query(this, glUtilsParamSize(param) * sizeof(GLint64), val); |
| 458 | m_glGetInteger64v_enc(this, param, query.hostStagingBuffer()); |
| 459 | } |
| 460 | |
| 461 | void GL2Encoder::safe_glGetIntegeri_v(GLenum param, GLuint index, GLint* val) { |
| 462 | ScopedQueryUpdate<GLint> query(this, sizeof(GLint), val); |
| 463 | m_glGetIntegeri_v_enc(this, param, index, query.hostStagingBuffer()); |
| 464 | } |
| 465 | |
| 466 | void GL2Encoder::safe_glGetInteger64i_v(GLenum param, GLuint index, GLint64* val) { |
| 467 | ScopedQueryUpdate<GLint64> query(this, sizeof(GLint64), val); |
| 468 | m_glGetInteger64i_v_enc(this, param, index, query.hostStagingBuffer()); |
| 469 | } |
| 470 | |
| 471 | void GL2Encoder::safe_glGetBooleani_v(GLenum param, GLuint index, GLboolean* val) { |
| 472 | ScopedQueryUpdate<GLboolean> query(this, sizeof(GLboolean), val); |
| 473 | m_glGetBooleani_v_enc(this, param, index, query.hostStagingBuffer()); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 474 | } |
| 475 | |
| 476 | void GL2Encoder::s_glFlush(void *self) |
| 477 | { |
| 478 | GL2Encoder *ctx = (GL2Encoder *) self; |
| 479 | ctx->m_glFlush_enc(self); |
| 480 | ctx->m_stream->flush(); |
| 481 | } |
| 482 | |
| 483 | const GLubyte *GL2Encoder::s_glGetString(void *self, GLenum name) |
| 484 | { |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 485 | GL2Encoder *ctx = (GL2Encoder *)self; |
David 'Digit' Turner | e01d5f4 | 2014-10-30 21:32:28 +0100 | [diff] [blame] | 486 | |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 487 | GLubyte *retval = (GLubyte *) ""; |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 488 | RET_AND_SET_ERROR_IF( |
| 489 | name != GL_VENDOR && |
| 490 | name != GL_RENDERER && |
| 491 | name != GL_VERSION && |
| 492 | name != GL_EXTENSIONS, |
| 493 | GL_INVALID_ENUM, |
| 494 | retval); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 495 | switch(name) { |
| 496 | case GL_VENDOR: |
| 497 | retval = gVendorString; |
| 498 | break; |
| 499 | case GL_RENDERER: |
| 500 | retval = gRendererString; |
| 501 | break; |
| 502 | case GL_VERSION: |
| 503 | retval = gVersionString; |
| 504 | break; |
| 505 | case GL_EXTENSIONS: |
| 506 | retval = gExtensionsString; |
| 507 | break; |
| 508 | } |
| 509 | return retval; |
| 510 | } |
| 511 | |
| 512 | void GL2Encoder::s_glPixelStorei(void *self, GLenum param, GLint value) |
| 513 | { |
| 514 | GL2Encoder *ctx = (GL2Encoder *)self; |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 515 | SET_ERROR_IF(!GLESv2Validation::pixelStoreParam(ctx, param), GL_INVALID_ENUM); |
| 516 | SET_ERROR_IF(!GLESv2Validation::pixelStoreValue(param, value), GL_INVALID_VALUE); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 517 | ctx->m_glPixelStorei_enc(ctx, param, value); |
| 518 | assert(ctx->m_state != NULL); |
| 519 | ctx->m_state->setPixelStore(param, value); |
| 520 | } |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 521 | void GL2Encoder::s_glBindBuffer(void *self, GLenum target, GLuint id) |
| 522 | { |
| 523 | GL2Encoder *ctx = (GL2Encoder *) self; |
| 524 | assert(ctx->m_state != NULL); |
| 525 | ctx->m_state->bindBuffer(target, id); |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 526 | ctx->m_state->addBuffer(id); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 527 | // TODO set error state if needed; |
| 528 | ctx->m_glBindBuffer_enc(self, target, id); |
| 529 | } |
| 530 | |
| 531 | void GL2Encoder::s_glBufferData(void * self, GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) |
| 532 | { |
| 533 | GL2Encoder *ctx = (GL2Encoder *) self; |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 534 | SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 535 | GLuint bufferId = ctx->m_state->getBuffer(target); |
| 536 | SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION); |
| 537 | SET_ERROR_IF(size<0, GL_INVALID_VALUE); |
| 538 | |
| 539 | ctx->m_shared->updateBufferData(bufferId, size, (void*)data); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 540 | ctx->m_shared->setBufferUsage(bufferId, usage); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 541 | ctx->m_glBufferData_enc(self, target, size, data, usage); |
| 542 | } |
| 543 | |
| 544 | void GL2Encoder::s_glBufferSubData(void * self, GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) |
| 545 | { |
| 546 | GL2Encoder *ctx = (GL2Encoder *) self; |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 547 | SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 548 | GLuint bufferId = ctx->m_state->getBuffer(target); |
| 549 | SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 550 | SET_ERROR_IF(ctx->isBufferTargetMapped(target), GL_INVALID_OPERATION); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 551 | |
| 552 | GLenum res = ctx->m_shared->subUpdateBufferData(bufferId, offset, size, (void*)data); |
| 553 | SET_ERROR_IF(res, res); |
| 554 | |
| 555 | ctx->m_glBufferSubData_enc(self, target, offset, size, data); |
| 556 | } |
| 557 | |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 558 | void GL2Encoder::s_glGenBuffers(void* self, GLsizei n, GLuint* buffers) { |
| 559 | GL2Encoder *ctx = (GL2Encoder *) self; |
| 560 | SET_ERROR_IF(n<0, GL_INVALID_VALUE); |
| 561 | ctx->m_glGenBuffers_enc(self, n, buffers); |
| 562 | for (int i = 0; i < n; i++) { |
| 563 | ctx->m_state->addBuffer(buffers[i]); |
| 564 | } |
| 565 | } |
| 566 | |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 567 | void GL2Encoder::s_glDeleteBuffers(void * self, GLsizei n, const GLuint * buffers) |
| 568 | { |
| 569 | GL2Encoder *ctx = (GL2Encoder *) self; |
| 570 | SET_ERROR_IF(n<0, GL_INVALID_VALUE); |
| 571 | for (int i=0; i<n; i++) { |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 572 | // Technically if the buffer is mapped, we should unmap it, but we won't |
| 573 | // use it anymore after this :) |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 574 | ctx->m_shared->deleteBufferData(buffers[i]); |
bohu | b0f0cdf | 2014-11-06 18:08:07 -0800 | [diff] [blame] | 575 | ctx->m_state->unBindBuffer(buffers[i]); |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 576 | ctx->m_state->removeBuffer(buffers[i]); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 577 | ctx->m_glDeleteBuffers_enc(self,1,&buffers[i]); |
| 578 | } |
| 579 | } |
| 580 | |
Evan Birenbaum | d51386b | 2016-04-13 12:53:09 -0700 | [diff] [blame] | 581 | static bool isValidVertexAttribIndex(void *self, GLuint indx) |
| 582 | { |
Lingfeng Yang | 0728990 | 2017-01-27 12:26:19 -0800 | [diff] [blame] | 583 | GL2Encoder *ctx = (GL2Encoder *)self; |
Evan Birenbaum | d51386b | 2016-04-13 12:53:09 -0700 | [diff] [blame] | 584 | GLint maxIndex; |
| 585 | ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex); |
| 586 | return indx < maxIndex; |
| 587 | } |
| 588 | |
Lingfeng Yang | 0728990 | 2017-01-27 12:26:19 -0800 | [diff] [blame] | 589 | #define VALIDATE_VERTEX_ATTRIB_INDEX(index) \ |
| 590 | SET_ERROR_WITH_MESSAGE_IF( \ |
| 591 | !isValidVertexAttribIndex(self, index), GL_INVALID_VALUE, \ |
| 592 | GLESv2Validation::vertexAttribIndexRangeErrorMsg, (ctx, index)); \ |
| 593 | |
David 'Digit' Turner | 02fdb69 | 2014-10-30 18:07:56 +0100 | [diff] [blame] | 594 | void GL2Encoder::s_glVertexAttribPointer(void *self, GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid * ptr) |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 595 | { |
| 596 | GL2Encoder *ctx = (GL2Encoder *)self; |
| 597 | assert(ctx->m_state != NULL); |
Lingfeng Yang | 0728990 | 2017-01-27 12:26:19 -0800 | [diff] [blame] | 598 | VALIDATE_VERTEX_ATTRIB_INDEX(indx); |
Evan Birenbaum | d51386b | 2016-04-13 12:53:09 -0700 | [diff] [blame] | 599 | SET_ERROR_IF((size < 1 || size > 4), GL_INVALID_VALUE); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 600 | SET_ERROR_IF(!GLESv2Validation::vertexAttribType(ctx, type), GL_INVALID_ENUM); |
Evan Birenbaum | d51386b | 2016-04-13 12:53:09 -0700 | [diff] [blame] | 601 | SET_ERROR_IF(stride < 0, GL_INVALID_VALUE); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 602 | SET_ERROR_IF((type == GL_INT_2_10_10_10_REV || |
| 603 | type == GL_UNSIGNED_INT_2_10_10_10_REV) && |
| 604 | size != 4, |
| 605 | GL_INVALID_OPERATION); |
| 606 | ctx->m_state->setVertexAttribBinding(indx, indx); |
| 607 | ctx->m_state->setVertexAttribFormat(indx, size, type, normalized, 0, false); |
| 608 | |
| 609 | GLsizei effectiveStride = stride; |
| 610 | if (stride == 0) { |
| 611 | effectiveStride = glSizeof(type) * size; |
| 612 | switch (type) { |
| 613 | case GL_INT_2_10_10_10_REV: |
| 614 | case GL_UNSIGNED_INT_2_10_10_10_REV: |
| 615 | effectiveStride /= 4; |
| 616 | break; |
| 617 | default: |
| 618 | break; |
| 619 | } |
| 620 | } |
| 621 | |
| 622 | ctx->m_state->bindIndexedBuffer(0, indx, ctx->m_state->currentArrayVbo(), (uintptr_t)ptr, 0, stride, effectiveStride); |
| 623 | |
Lingfeng Yang | fe2a31d | 2016-12-02 08:02:15 -0800 | [diff] [blame] | 624 | if (ctx->m_state->currentArrayVbo() != 0) { |
| 625 | ctx->glVertexAttribPointerOffset(ctx, indx, size, type, normalized, stride, (uintptr_t)ptr); |
| 626 | } else { |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 627 | SET_ERROR_IF(ctx->m_state->currentVertexArrayObject() != 0 && ptr, GL_INVALID_OPERATION); |
| 628 | // wait for client-array handler |
Lingfeng Yang | fe2a31d | 2016-12-02 08:02:15 -0800 | [diff] [blame] | 629 | } |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 630 | } |
| 631 | |
| 632 | void GL2Encoder::s_glGetIntegerv(void *self, GLenum param, GLint *ptr) |
| 633 | { |
| 634 | GL2Encoder *ctx = (GL2Encoder *) self; |
| 635 | assert(ctx->m_state != NULL); |
| 636 | GLClientState* state = ctx->m_state; |
| 637 | |
| 638 | switch (param) { |
Lingfeng Yang | a16eb2e | 2018-02-23 11:26:53 -0800 | [diff] [blame] | 639 | case GL_NUM_EXTENSIONS: |
| 640 | *ptr = (int)ctx->m_currExtensionsArray.size(); |
| 641 | break; |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 642 | case GL_MAJOR_VERSION: |
Lingfeng Yang | 324c845 | 2017-02-17 09:56:26 -0800 | [diff] [blame] | 643 | *ptr = ctx->m_deviceMajorVersion; |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 644 | break; |
| 645 | case GL_MINOR_VERSION: |
Lingfeng Yang | 324c845 | 2017-02-17 09:56:26 -0800 | [diff] [blame] | 646 | *ptr = ctx->m_deviceMinorVersion; |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 647 | break; |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 648 | case GL_NUM_SHADER_BINARY_FORMATS: |
| 649 | *ptr = 0; |
| 650 | break; |
| 651 | case GL_SHADER_BINARY_FORMATS: |
| 652 | // do nothing |
| 653 | break; |
| 654 | |
| 655 | case GL_COMPRESSED_TEXTURE_FORMATS: { |
| 656 | GLint *compressedTextureFormats = ctx->getCompressedTextureFormats(); |
| 657 | if (ctx->m_num_compressedTextureFormats > 0 && |
| 658 | compressedTextureFormats != NULL) { |
| 659 | memcpy(ptr, compressedTextureFormats, |
| 660 | ctx->m_num_compressedTextureFormats * sizeof(GLint)); |
| 661 | } |
| 662 | break; |
| 663 | } |
| 664 | |
| 665 | case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: |
| 666 | case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: |
| 667 | case GL_MAX_TEXTURE_IMAGE_UNITS: |
Lingfeng Yang | 80a3633 | 2017-07-09 10:58:07 -0700 | [diff] [blame] | 668 | ctx->safe_glGetIntegerv(param, ptr); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 669 | *ptr = MIN(*ptr, GLClientState::MAX_TEXTURE_UNITS); |
| 670 | break; |
| 671 | |
| 672 | case GL_TEXTURE_BINDING_2D: |
| 673 | *ptr = state->getBoundTexture(GL_TEXTURE_2D); |
| 674 | break; |
| 675 | case GL_TEXTURE_BINDING_EXTERNAL_OES: |
| 676 | *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES); |
| 677 | break; |
| 678 | |
Lingfeng Yang | b017698 | 2016-03-01 21:27:49 -0800 | [diff] [blame] | 679 | case GL_MAX_VERTEX_ATTRIBS: |
| 680 | if (!ctx->m_state->getClientStateParameter<GLint>(param, ptr)) { |
Lingfeng Yang | 80a3633 | 2017-07-09 10:58:07 -0700 | [diff] [blame] | 681 | ctx->safe_glGetIntegerv(param, ptr); |
Lingfeng Yang | b017698 | 2016-03-01 21:27:49 -0800 | [diff] [blame] | 682 | ctx->m_state->setMaxVertexAttribs(*ptr); |
Yahan Zhou | a5c3684 | 2016-06-01 12:49:39 -0700 | [diff] [blame] | 683 | } |
| 684 | break; |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 685 | case GL_MAX_VERTEX_ATTRIB_STRIDE: |
| 686 | if (ctx->m_max_vertexAttribStride != 0) { |
| 687 | *ptr = ctx->m_max_vertexAttribStride; |
| 688 | } else { |
Lingfeng Yang | 80a3633 | 2017-07-09 10:58:07 -0700 | [diff] [blame] | 689 | ctx->safe_glGetIntegerv(param, ptr); |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 690 | ctx->m_max_vertexAttribStride = *ptr; |
| 691 | } |
| 692 | break; |
Lizhe Liu | e41f4ef | 2015-05-27 11:13:23 +0800 | [diff] [blame] | 693 | case GL_MAX_CUBE_MAP_TEXTURE_SIZE: |
| 694 | if (ctx->m_max_cubeMapTextureSize != 0) { |
| 695 | *ptr = ctx->m_max_cubeMapTextureSize; |
| 696 | } else { |
Lingfeng Yang | 80a3633 | 2017-07-09 10:58:07 -0700 | [diff] [blame] | 697 | ctx->safe_glGetIntegerv(param, ptr); |
Lizhe Liu | e41f4ef | 2015-05-27 11:13:23 +0800 | [diff] [blame] | 698 | ctx->m_max_cubeMapTextureSize = *ptr; |
| 699 | } |
| 700 | break; |
| 701 | case GL_MAX_RENDERBUFFER_SIZE: |
| 702 | if (ctx->m_max_renderBufferSize != 0) { |
| 703 | *ptr = ctx->m_max_renderBufferSize; |
| 704 | } else { |
Lingfeng Yang | 80a3633 | 2017-07-09 10:58:07 -0700 | [diff] [blame] | 705 | ctx->safe_glGetIntegerv(param, ptr); |
Lizhe Liu | e41f4ef | 2015-05-27 11:13:23 +0800 | [diff] [blame] | 706 | ctx->m_max_renderBufferSize = *ptr; |
| 707 | } |
| 708 | break; |
| 709 | case GL_MAX_TEXTURE_SIZE: |
| 710 | if (ctx->m_max_textureSize != 0) { |
| 711 | *ptr = ctx->m_max_textureSize; |
| 712 | } else { |
Lingfeng Yang | 80a3633 | 2017-07-09 10:58:07 -0700 | [diff] [blame] | 713 | ctx->safe_glGetIntegerv(param, ptr); |
Lizhe Liu | e41f4ef | 2015-05-27 11:13:23 +0800 | [diff] [blame] | 714 | ctx->m_max_textureSize = *ptr; |
Lingfeng Yang | b017698 | 2016-03-01 21:27:49 -0800 | [diff] [blame] | 715 | } |
| 716 | break; |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 717 | case GL_MAX_3D_TEXTURE_SIZE: |
| 718 | if (ctx->m_max_3d_textureSize != 0) { |
| 719 | *ptr = ctx->m_max_3d_textureSize; |
| 720 | } else { |
Lingfeng Yang | 80a3633 | 2017-07-09 10:58:07 -0700 | [diff] [blame] | 721 | ctx->safe_glGetIntegerv(param, ptr); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 722 | ctx->m_max_3d_textureSize = *ptr; |
| 723 | } |
| 724 | break; |
| 725 | case GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT: |
| 726 | if (ctx->m_ssbo_offset_align != 0) { |
| 727 | *ptr = ctx->m_ssbo_offset_align; |
| 728 | } else { |
Lingfeng Yang | 80a3633 | 2017-07-09 10:58:07 -0700 | [diff] [blame] | 729 | ctx->safe_glGetIntegerv(param, ptr); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 730 | ctx->m_ssbo_offset_align = *ptr; |
| 731 | } |
| 732 | break; |
| 733 | case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT: |
| 734 | if (ctx->m_ubo_offset_align != 0) { |
| 735 | *ptr = ctx->m_ubo_offset_align; |
| 736 | } else { |
Lingfeng Yang | 80a3633 | 2017-07-09 10:58:07 -0700 | [diff] [blame] | 737 | ctx->safe_glGetIntegerv(param, ptr); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 738 | ctx->m_ubo_offset_align = *ptr; |
| 739 | } |
| 740 | break; |
| 741 | // Desktop OpenGL can allow a mindboggling # samples per pixel (such as 64). |
| 742 | // Limit to 4 (spec minimum) to keep dEQP tests from timing out. |
| 743 | case GL_MAX_SAMPLES: |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 744 | case GL_MAX_COLOR_TEXTURE_SAMPLES: |
| 745 | case GL_MAX_INTEGER_SAMPLES: |
| 746 | case GL_MAX_DEPTH_TEXTURE_SAMPLES: |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 747 | *ptr = 4; |
| 748 | break; |
Lingfeng Yang | c9b597b | 2017-07-08 17:21:03 -0700 | [diff] [blame] | 749 | // Checks for version-incompatible enums. |
| 750 | // Not allowed in vanilla ES 2.0. |
| 751 | case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS: |
| 752 | case GL_MAX_UNIFORM_BUFFER_BINDINGS: |
| 753 | SET_ERROR_IF(ctx->majorVersion() < 3, GL_INVALID_ENUM); |
Lingfeng Yang | 80a3633 | 2017-07-09 10:58:07 -0700 | [diff] [blame] | 754 | ctx->safe_glGetIntegerv(param, ptr); |
Lingfeng Yang | c9b597b | 2017-07-08 17:21:03 -0700 | [diff] [blame] | 755 | break; |
| 756 | case GL_MAX_COLOR_ATTACHMENTS: |
| 757 | case GL_MAX_DRAW_BUFFERS: |
| 758 | SET_ERROR_IF(ctx->majorVersion() < 3 && |
| 759 | !ctx->hasExtension("GL_EXT_draw_buffers"), GL_INVALID_ENUM); |
Lingfeng Yang | 80a3633 | 2017-07-09 10:58:07 -0700 | [diff] [blame] | 760 | ctx->safe_glGetIntegerv(param, ptr); |
Lingfeng Yang | c9b597b | 2017-07-08 17:21:03 -0700 | [diff] [blame] | 761 | break; |
| 762 | // Not allowed in ES 3.0. |
| 763 | case GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS: |
| 764 | case GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS: |
| 765 | case GL_MAX_VERTEX_ATTRIB_BINDINGS: |
| 766 | SET_ERROR_IF(ctx->majorVersion() < 3 || |
| 767 | (ctx->majorVersion() == 3 && |
| 768 | ctx->minorVersion() == 0), GL_INVALID_ENUM); |
Lingfeng Yang | 80a3633 | 2017-07-09 10:58:07 -0700 | [diff] [blame] | 769 | ctx->safe_glGetIntegerv(param, ptr); |
Lingfeng Yang | c9b597b | 2017-07-08 17:21:03 -0700 | [diff] [blame] | 770 | break; |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 771 | default: |
| 772 | if (!ctx->m_state->getClientStateParameter<GLint>(param, ptr)) { |
Lingfeng Yang | 80a3633 | 2017-07-09 10:58:07 -0700 | [diff] [blame] | 773 | ctx->safe_glGetIntegerv(param, ptr); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 774 | } |
| 775 | break; |
| 776 | } |
| 777 | } |
| 778 | |
| 779 | |
| 780 | void GL2Encoder::s_glGetFloatv(void *self, GLenum param, GLfloat *ptr) |
| 781 | { |
| 782 | GL2Encoder *ctx = (GL2Encoder *)self; |
| 783 | assert(ctx->m_state != NULL); |
| 784 | GLClientState* state = ctx->m_state; |
| 785 | |
| 786 | switch (param) { |
| 787 | case GL_NUM_SHADER_BINARY_FORMATS: |
| 788 | *ptr = 0; |
| 789 | break; |
| 790 | case GL_SHADER_BINARY_FORMATS: |
| 791 | // do nothing |
| 792 | break; |
| 793 | |
| 794 | case GL_COMPRESSED_TEXTURE_FORMATS: { |
| 795 | GLint *compressedTextureFormats = ctx->getCompressedTextureFormats(); |
| 796 | if (ctx->m_num_compressedTextureFormats > 0 && |
| 797 | compressedTextureFormats != NULL) { |
| 798 | for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) { |
| 799 | ptr[i] = (GLfloat) compressedTextureFormats[i]; |
| 800 | } |
| 801 | } |
| 802 | break; |
| 803 | } |
| 804 | |
| 805 | case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: |
| 806 | case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: |
| 807 | case GL_MAX_TEXTURE_IMAGE_UNITS: |
Lingfeng Yang | 80a3633 | 2017-07-09 10:58:07 -0700 | [diff] [blame] | 808 | ctx->safe_glGetFloatv(param, ptr); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 809 | *ptr = MIN(*ptr, (GLfloat)GLClientState::MAX_TEXTURE_UNITS); |
| 810 | break; |
| 811 | |
| 812 | case GL_TEXTURE_BINDING_2D: |
| 813 | *ptr = (GLfloat)state->getBoundTexture(GL_TEXTURE_2D); |
| 814 | break; |
| 815 | case GL_TEXTURE_BINDING_EXTERNAL_OES: |
| 816 | *ptr = (GLfloat)state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES); |
| 817 | break; |
| 818 | |
| 819 | default: |
| 820 | if (!ctx->m_state->getClientStateParameter<GLfloat>(param, ptr)) { |
Lingfeng Yang | 80a3633 | 2017-07-09 10:58:07 -0700 | [diff] [blame] | 821 | ctx->safe_glGetFloatv(param, ptr); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 822 | } |
| 823 | break; |
| 824 | } |
| 825 | } |
| 826 | |
| 827 | |
| 828 | void GL2Encoder::s_glGetBooleanv(void *self, GLenum param, GLboolean *ptr) |
| 829 | { |
| 830 | GL2Encoder *ctx = (GL2Encoder *)self; |
| 831 | assert(ctx->m_state != NULL); |
| 832 | GLClientState* state = ctx->m_state; |
| 833 | |
| 834 | switch (param) { |
| 835 | case GL_NUM_SHADER_BINARY_FORMATS: |
| 836 | *ptr = GL_FALSE; |
| 837 | break; |
| 838 | case GL_SHADER_BINARY_FORMATS: |
| 839 | // do nothing |
| 840 | break; |
| 841 | |
| 842 | case GL_COMPRESSED_TEXTURE_FORMATS: { |
| 843 | GLint *compressedTextureFormats = ctx->getCompressedTextureFormats(); |
| 844 | if (ctx->m_num_compressedTextureFormats > 0 && |
| 845 | compressedTextureFormats != NULL) { |
| 846 | for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) { |
| 847 | ptr[i] = compressedTextureFormats[i] != 0 ? GL_TRUE : GL_FALSE; |
| 848 | } |
| 849 | } |
| 850 | break; |
| 851 | } |
| 852 | |
| 853 | case GL_TEXTURE_BINDING_2D: |
| 854 | *ptr = state->getBoundTexture(GL_TEXTURE_2D) != 0 ? GL_TRUE : GL_FALSE; |
| 855 | break; |
| 856 | case GL_TEXTURE_BINDING_EXTERNAL_OES: |
| 857 | *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES) != 0 |
| 858 | ? GL_TRUE : GL_FALSE; |
| 859 | break; |
| 860 | |
| 861 | default: |
| 862 | if (!ctx->m_state->getClientStateParameter<GLboolean>(param, ptr)) { |
Lingfeng Yang | 80a3633 | 2017-07-09 10:58:07 -0700 | [diff] [blame] | 863 | ctx->safe_glGetBooleanv(param, ptr); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 864 | } |
bohu | 05101d2 | 2014-11-17 16:28:42 -0800 | [diff] [blame] | 865 | *ptr = (*ptr != 0) ? GL_TRUE : GL_FALSE; |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 866 | break; |
| 867 | } |
| 868 | } |
| 869 | |
| 870 | |
| 871 | void GL2Encoder::s_glEnableVertexAttribArray(void *self, GLuint index) |
| 872 | { |
| 873 | GL2Encoder *ctx = (GL2Encoder *)self; |
| 874 | assert(ctx->m_state); |
Lingfeng Yang | 0728990 | 2017-01-27 12:26:19 -0800 | [diff] [blame] | 875 | VALIDATE_VERTEX_ATTRIB_INDEX(index); |
Lingfeng Yang | fe2a31d | 2016-12-02 08:02:15 -0800 | [diff] [blame] | 876 | ctx->m_glEnableVertexAttribArray_enc(ctx, index); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 877 | ctx->m_state->enable(index, 1); |
| 878 | } |
| 879 | |
| 880 | void GL2Encoder::s_glDisableVertexAttribArray(void *self, GLuint index) |
| 881 | { |
| 882 | GL2Encoder *ctx = (GL2Encoder *)self; |
| 883 | assert(ctx->m_state); |
Lingfeng Yang | 0728990 | 2017-01-27 12:26:19 -0800 | [diff] [blame] | 884 | VALIDATE_VERTEX_ATTRIB_INDEX(index); |
Lingfeng Yang | fe2a31d | 2016-12-02 08:02:15 -0800 | [diff] [blame] | 885 | ctx->m_glDisableVertexAttribArray_enc(ctx, index); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 886 | ctx->m_state->enable(index, 0); |
| 887 | } |
| 888 | |
| 889 | |
| 890 | void GL2Encoder::s_glGetVertexAttribiv(void *self, GLuint index, GLenum pname, GLint *params) |
| 891 | { |
| 892 | GL2Encoder *ctx = (GL2Encoder *)self; |
| 893 | assert(ctx->m_state); |
Lingfeng Yang | 0f50808 | 2016-04-08 12:38:35 -0700 | [diff] [blame] | 894 | GLint maxIndex; |
| 895 | ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex); |
| 896 | SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 897 | |
| 898 | if (!ctx->m_state->getVertexAttribParameter<GLint>(index, pname, params)) { |
| 899 | ctx->m_glGetVertexAttribiv_enc(self, index, pname, params); |
| 900 | } |
| 901 | } |
| 902 | |
| 903 | void GL2Encoder::s_glGetVertexAttribfv(void *self, GLuint index, GLenum pname, GLfloat *params) |
| 904 | { |
| 905 | GL2Encoder *ctx = (GL2Encoder *)self; |
| 906 | assert(ctx->m_state); |
Lingfeng Yang | 0f50808 | 2016-04-08 12:38:35 -0700 | [diff] [blame] | 907 | GLint maxIndex; |
| 908 | ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex); |
| 909 | SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 910 | |
| 911 | if (!ctx->m_state->getVertexAttribParameter<GLfloat>(index, pname, params)) { |
| 912 | ctx->m_glGetVertexAttribfv_enc(self, index, pname, params); |
| 913 | } |
| 914 | } |
| 915 | |
| 916 | void GL2Encoder::s_glGetVertexAttribPointerv(void *self, GLuint index, GLenum pname, GLvoid **pointer) |
| 917 | { |
| 918 | GL2Encoder *ctx = (GL2Encoder *)self; |
| 919 | if (ctx->m_state == NULL) return; |
Lingfeng Yang | 5e10043 | 2016-04-08 12:46:42 -0700 | [diff] [blame] | 920 | GLint maxIndex; |
| 921 | ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex); |
| 922 | SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE); |
| 923 | SET_ERROR_IF(pname != GL_VERTEX_ATTRIB_ARRAY_POINTER, GL_INVALID_ENUM); |
David 'Digit' Turner | e01d5f4 | 2014-10-30 21:32:28 +0100 | [diff] [blame] | 924 | (void)pname; |
| 925 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 926 | *pointer = (GLvoid*)(ctx->m_state->getCurrAttributeBindingInfo(index).offset); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 927 | } |
| 928 | |
Lingfeng Yang | 8e2b6e0 | 2016-10-14 11:20:45 -0700 | [diff] [blame] | 929 | void GL2Encoder::calcIndexRange(const void* indices, |
| 930 | GLenum type, |
| 931 | GLsizei count, |
| 932 | int* minIndex_out, |
| 933 | int* maxIndex_out) { |
| 934 | switch(type) { |
| 935 | case GL_BYTE: |
| 936 | case GL_UNSIGNED_BYTE: |
| 937 | GLUtils::minmaxExcept( |
| 938 | (unsigned char *)indices, count, |
| 939 | minIndex_out, maxIndex_out, |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 940 | m_primitiveRestartEnabled, GLUtils::primitiveRestartIndex<unsigned char>()); |
Lingfeng Yang | 8e2b6e0 | 2016-10-14 11:20:45 -0700 | [diff] [blame] | 941 | break; |
| 942 | case GL_SHORT: |
| 943 | case GL_UNSIGNED_SHORT: |
| 944 | GLUtils::minmaxExcept( |
| 945 | (unsigned short *)indices, count, |
| 946 | minIndex_out, maxIndex_out, |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 947 | m_primitiveRestartEnabled, GLUtils::primitiveRestartIndex<unsigned short>()); |
Lingfeng Yang | 8e2b6e0 | 2016-10-14 11:20:45 -0700 | [diff] [blame] | 948 | break; |
| 949 | case GL_INT: |
| 950 | case GL_UNSIGNED_INT: |
| 951 | GLUtils::minmaxExcept( |
| 952 | (unsigned int *)indices, count, |
| 953 | minIndex_out, maxIndex_out, |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 954 | m_primitiveRestartEnabled, GLUtils::primitiveRestartIndex<unsigned int>()); |
Lingfeng Yang | 8e2b6e0 | 2016-10-14 11:20:45 -0700 | [diff] [blame] | 955 | break; |
| 956 | default: |
| 957 | ALOGE("unsupported index buffer type %d\n", type); |
| 958 | } |
| 959 | } |
| 960 | |
| 961 | void* GL2Encoder::recenterIndices(const void* src, |
| 962 | GLenum type, |
| 963 | GLsizei count, |
| 964 | int minIndex) { |
| 965 | |
| 966 | void* adjustedIndices = (void*)src; |
| 967 | |
| 968 | if (minIndex != 0) { |
| 969 | adjustedIndices = m_fixedBuffer.alloc(glSizeof(type) * count); |
| 970 | switch(type) { |
| 971 | case GL_BYTE: |
| 972 | case GL_UNSIGNED_BYTE: |
| 973 | GLUtils::shiftIndicesExcept( |
| 974 | (unsigned char *)src, |
| 975 | (unsigned char *)adjustedIndices, |
| 976 | count, -minIndex, |
| 977 | m_primitiveRestartEnabled, |
| 978 | (unsigned char)m_primitiveRestartIndex); |
| 979 | break; |
| 980 | case GL_SHORT: |
| 981 | case GL_UNSIGNED_SHORT: |
| 982 | GLUtils::shiftIndicesExcept( |
| 983 | (unsigned short *)src, |
| 984 | (unsigned short *)adjustedIndices, |
| 985 | count, -minIndex, |
| 986 | m_primitiveRestartEnabled, |
| 987 | (unsigned short)m_primitiveRestartIndex); |
| 988 | break; |
| 989 | case GL_INT: |
| 990 | case GL_UNSIGNED_INT: |
| 991 | GLUtils::shiftIndicesExcept( |
| 992 | (unsigned int *)src, |
| 993 | (unsigned int *)adjustedIndices, |
| 994 | count, -minIndex, |
| 995 | m_primitiveRestartEnabled, |
| 996 | (unsigned int)m_primitiveRestartIndex); |
| 997 | break; |
| 998 | default: |
| 999 | ALOGE("unsupported index buffer type %d\n", type); |
| 1000 | } |
| 1001 | } |
| 1002 | |
| 1003 | return adjustedIndices; |
| 1004 | } |
| 1005 | |
| 1006 | void GL2Encoder::getBufferIndexRange(BufferData* buf, |
| 1007 | const void* dataWithOffset, |
| 1008 | GLenum type, |
Lingfeng Yang | 1ae9d73 | 2016-12-12 16:17:02 -0800 | [diff] [blame] | 1009 | size_t count, |
| 1010 | size_t offset, |
Lingfeng Yang | 8e2b6e0 | 2016-10-14 11:20:45 -0700 | [diff] [blame] | 1011 | int* minIndex_out, |
| 1012 | int* maxIndex_out) { |
| 1013 | |
| 1014 | if (buf->m_indexRangeCache.findRange( |
Lingfeng Yang | 1ae9d73 | 2016-12-12 16:17:02 -0800 | [diff] [blame] | 1015 | type, offset, count, |
Lingfeng Yang | 8e2b6e0 | 2016-10-14 11:20:45 -0700 | [diff] [blame] | 1016 | m_primitiveRestartEnabled, |
| 1017 | minIndex_out, |
| 1018 | maxIndex_out)) { |
| 1019 | return; |
| 1020 | } |
| 1021 | |
| 1022 | calcIndexRange(dataWithOffset, type, count, minIndex_out, maxIndex_out); |
| 1023 | |
| 1024 | buf->m_indexRangeCache.addRange( |
Lingfeng Yang | 1ae9d73 | 2016-12-12 16:17:02 -0800 | [diff] [blame] | 1025 | type, offset, count, m_primitiveRestartEnabled, |
Lingfeng Yang | 8e2b6e0 | 2016-10-14 11:20:45 -0700 | [diff] [blame] | 1026 | *minIndex_out, *maxIndex_out); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 1027 | |
| 1028 | ALOGV("%s: got range [%u %u] pr? %d", __FUNCTION__, *minIndex_out, *maxIndex_out, m_primitiveRestartEnabled); |
Lingfeng Yang | 8e2b6e0 | 2016-10-14 11:20:45 -0700 | [diff] [blame] | 1029 | } |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1030 | |
Lingfeng Yang | fe2a31d | 2016-12-02 08:02:15 -0800 | [diff] [blame] | 1031 | // For detecting legacy usage of glVertexAttribPointer |
| 1032 | void GL2Encoder::getVBOUsage(bool* hasClientArrays, bool* hasVBOs) const { |
| 1033 | if (hasClientArrays) *hasClientArrays = false; |
| 1034 | if (hasVBOs) *hasVBOs = false; |
| 1035 | |
| 1036 | for (int i = 0; i < m_state->nLocations(); i++) { |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 1037 | const GLClientState::VertexAttribState& state = m_state->getState(i); |
| 1038 | if (state.enabled) { |
| 1039 | const GLClientState::BufferBinding& curr_binding = m_state->getCurrAttributeBindingInfo(i); |
| 1040 | GLuint bufferObject = curr_binding.buffer; |
| 1041 | if (bufferObject == 0 && curr_binding.offset && hasClientArrays) { |
Lingfeng Yang | fe2a31d | 2016-12-02 08:02:15 -0800 | [diff] [blame] | 1042 | *hasClientArrays = true; |
| 1043 | } |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 1044 | if (bufferObject != 0 && hasVBOs) { |
Lingfeng Yang | fe2a31d | 2016-12-02 08:02:15 -0800 | [diff] [blame] | 1045 | *hasVBOs = true; |
| 1046 | } |
| 1047 | } |
| 1048 | } |
| 1049 | } |
| 1050 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 1051 | void GL2Encoder::sendVertexAttributes(GLint first, GLsizei count, bool hasClientArrays, GLsizei primcount) |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1052 | { |
| 1053 | assert(m_state); |
| 1054 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 1055 | GLuint currentVao = m_state->currentVertexArrayObject(); |
Lingfeng Yang | 398162b | 2016-05-26 14:18:33 -0700 | [diff] [blame] | 1056 | GLuint lastBoundVbo = m_state->currentArrayVbo(); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1057 | for (int i = 0; i < m_state->nLocations(); i++) { |
| 1058 | bool enableDirty; |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 1059 | const GLClientState::VertexAttribState& state = m_state->getStateAndEnableDirty(i, &enableDirty); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1060 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 1061 | if (!enableDirty && !state.enabled) { |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1062 | continue; |
| 1063 | } |
| 1064 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 1065 | if (state.enabled) { |
| 1066 | const GLClientState::BufferBinding& curr_binding = m_state->getCurrAttributeBindingInfo(i); |
| 1067 | GLuint bufferObject = curr_binding.buffer; |
| 1068 | if (hasClientArrays && lastBoundVbo != bufferObject) { |
| 1069 | this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, bufferObject); |
| 1070 | lastBoundVbo = bufferObject; |
Lingfeng Yang | 398162b | 2016-05-26 14:18:33 -0700 | [diff] [blame] | 1071 | } |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1072 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 1073 | int divisor = curr_binding.divisor; |
| 1074 | int stride = curr_binding.stride; |
| 1075 | int effectiveStride = curr_binding.effectiveStride; |
| 1076 | uintptr_t offset = curr_binding.offset; |
Lingfeng Yang | 4e5446b | 2017-02-15 08:44:21 -0800 | [diff] [blame] | 1077 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 1078 | int firstIndex = effectiveStride * first; |
Lingfeng Yang | 4e5446b | 2017-02-15 08:44:21 -0800 | [diff] [blame] | 1079 | if (firstIndex && divisor && !primcount) { |
| 1080 | // If firstIndex != 0 according to effectiveStride * first, |
| 1081 | // it needs to be adjusted if a divisor has been specified, |
| 1082 | // even if we are not in glDraw***Instanced. |
| 1083 | firstIndex = 0; |
| 1084 | } |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1085 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 1086 | if (bufferObject == 0) { |
| 1087 | unsigned int datalen = state.elementSize * count; |
| 1088 | if (divisor && primcount) { |
| 1089 | ALOGV("%s: divisor for att %d: %d, w/ stride %d (effective stride %d) size %d type 0x%x) datalen %u", |
| 1090 | __FUNCTION__, i, divisor, state.stride, effectiveStride, state.elementSize, state.type, datalen); |
| 1091 | int actual_count = std::max(1, (int)((primcount + divisor - 1) / divisor)); |
| 1092 | datalen = state.elementSize * actual_count; |
| 1093 | ALOGV("%s: actual datalen %u", __FUNCTION__, datalen); |
| 1094 | } |
| 1095 | if (state.elementSize == 0) { |
Yahan Zhou | 3f2f1b4 | 2016-12-01 13:49:44 -0800 | [diff] [blame] | 1096 | // The vertex attribute array is uninitialized. Abandon it. |
| 1097 | ALOGE("a vertex attribute array is uninitialized. Skipping corresponding vertex attribute."); |
| 1098 | this->m_glDisableVertexAttribArray_enc(this, i); |
| 1099 | continue; |
| 1100 | } |
Yahan Zhou | 5507c04 | 2016-06-01 17:24:28 -0700 | [diff] [blame] | 1101 | m_glEnableVertexAttribArray_enc(this, i); |
Lingfeng Yang | 000cf4c | 2017-01-25 08:09:02 -0800 | [diff] [blame] | 1102 | |
| 1103 | if (datalen && (!offset || !((unsigned char*)offset + firstIndex))) { |
| 1104 | ALOGD("%s: bad offset / len!!!!!", __FUNCTION__); |
| 1105 | continue; |
| 1106 | } |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 1107 | if (state.isInt) { |
| 1108 | this->glVertexAttribIPointerDataAEMU(this, i, state.size, state.type, stride, (unsigned char *)offset + firstIndex, datalen); |
| 1109 | } else { |
| 1110 | this->glVertexAttribPointerData(this, i, state.size, state.type, state.normalized, stride, (unsigned char *)offset + firstIndex, datalen); |
| 1111 | } |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1112 | } else { |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 1113 | const BufferData* buf = m_shared->getBufferData(bufferObject); |
Yahan Zhou | 5507c04 | 2016-06-01 17:24:28 -0700 | [diff] [blame] | 1114 | // The following expression actually means bufLen = stride*count; |
| 1115 | // But the last element doesn't have to fill up the whole stride. |
| 1116 | // So it becomes the current form. |
Lingfeng Yang | 5fe9901 | 2017-01-18 09:17:09 -0800 | [diff] [blame] | 1117 | unsigned int bufLen = effectiveStride * (count ? (count - 1) : 0) + state.elementSize; |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 1118 | if (divisor && primcount) { |
| 1119 | int actual_count = std::max(1, (int)((primcount + divisor - 1) / divisor)); |
Lingfeng Yang | 5fe9901 | 2017-01-18 09:17:09 -0800 | [diff] [blame] | 1120 | bufLen = effectiveStride * (actual_count ? (actual_count - 1) : 0) + state.elementSize; |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 1121 | } |
Yahan Zhou | 5507c04 | 2016-06-01 17:24:28 -0700 | [diff] [blame] | 1122 | if (buf && firstIndex >= 0 && firstIndex + bufLen <= buf->m_size) { |
Lingfeng Yang | fe2a31d | 2016-12-02 08:02:15 -0800 | [diff] [blame] | 1123 | if (hasClientArrays) { |
| 1124 | m_glEnableVertexAttribArray_enc(this, i); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 1125 | if (state.isInt) { |
| 1126 | this->glVertexAttribIPointerOffsetAEMU(this, i, state.size, state.type, stride, offset + firstIndex); |
| 1127 | } else { |
| 1128 | this->glVertexAttribPointerOffset(this, i, state.size, state.type, state.normalized, stride, offset + firstIndex); |
| 1129 | } |
Lingfeng Yang | fe2a31d | 2016-12-02 08:02:15 -0800 | [diff] [blame] | 1130 | } |
Yahan Zhou | 5507c04 | 2016-06-01 17:24:28 -0700 | [diff] [blame] | 1131 | } else { |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 1132 | ALOGE("a vertex attribute index out of boundary is detected. Skipping corresponding vertex attribute. buf=%p", buf); |
Lingfeng Yang | 8d9d6c6 | 2017-01-18 09:26:19 -0800 | [diff] [blame] | 1133 | if (buf) { |
| 1134 | ALOGE("Out of bounds vertex attribute info: " |
| 1135 | "clientArray? %d attribute %d vbo %u allocedBufferSize %u bufferDataSpecified? %d wantedStart %u wantedEnd %u", |
| 1136 | hasClientArrays, i, bufferObject, buf->m_size, buf != NULL, firstIndex, firstIndex + bufLen); |
| 1137 | } |
| 1138 | m_glDisableVertexAttribArray_enc(this, i); |
Yahan Zhou | 5507c04 | 2016-06-01 17:24:28 -0700 | [diff] [blame] | 1139 | } |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1140 | } |
| 1141 | } else { |
Lingfeng Yang | fe2a31d | 2016-12-02 08:02:15 -0800 | [diff] [blame] | 1142 | if (hasClientArrays) { |
| 1143 | this->m_glDisableVertexAttribArray_enc(this, i); |
| 1144 | } |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1145 | } |
| 1146 | } |
Lingfeng Yang | 398162b | 2016-05-26 14:18:33 -0700 | [diff] [blame] | 1147 | |
Lingfeng Yang | fe2a31d | 2016-12-02 08:02:15 -0800 | [diff] [blame] | 1148 | if (hasClientArrays && lastBoundVbo != m_state->currentArrayVbo()) { |
Lingfeng Yang | 398162b | 2016-05-26 14:18:33 -0700 | [diff] [blame] | 1149 | this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, m_state->currentArrayVbo()); |
| 1150 | } |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1151 | } |
| 1152 | |
Lingfeng Yang | 8e2b6e0 | 2016-10-14 11:20:45 -0700 | [diff] [blame] | 1153 | void GL2Encoder::flushDrawCall() { |
Lingfeng Yang | 1ebb33c | 2017-01-19 08:04:48 -0800 | [diff] [blame] | 1154 | // This used to be every other draw call, but |
| 1155 | // now that we are using real GPU buffers on host, |
| 1156 | // set this to every 200 draw calls |
| 1157 | // (tuned on z840 linux NVIDIA Quadro K2200) |
| 1158 | if (m_drawCallFlushCount % 200 == 0) { |
Lingfeng Yang | 8e2b6e0 | 2016-10-14 11:20:45 -0700 | [diff] [blame] | 1159 | m_stream->flush(); |
| 1160 | } |
| 1161 | m_drawCallFlushCount++; |
| 1162 | } |
| 1163 | |
Evan Birenbaum | d51386b | 2016-04-13 12:53:09 -0700 | [diff] [blame] | 1164 | static bool isValidDrawMode(GLenum mode) |
| 1165 | { |
| 1166 | bool retval = false; |
| 1167 | switch (mode) { |
| 1168 | case GL_POINTS: |
| 1169 | case GL_LINE_STRIP: |
| 1170 | case GL_LINE_LOOP: |
| 1171 | case GL_LINES: |
| 1172 | case GL_TRIANGLE_STRIP: |
| 1173 | case GL_TRIANGLE_FAN: |
| 1174 | case GL_TRIANGLES: |
| 1175 | retval = true; |
| 1176 | } |
| 1177 | return retval; |
| 1178 | } |
| 1179 | |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1180 | void GL2Encoder::s_glDrawArrays(void *self, GLenum mode, GLint first, GLsizei count) |
| 1181 | { |
| 1182 | GL2Encoder *ctx = (GL2Encoder *)self; |
Evan Birenbaum | d51386b | 2016-04-13 12:53:09 -0700 | [diff] [blame] | 1183 | assert(ctx->m_state != NULL); |
| 1184 | SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM); |
| 1185 | SET_ERROR_IF(count < 0, GL_INVALID_VALUE); |
Yahan Zhou | d6217a5 | 2016-02-10 16:10:46 -0800 | [diff] [blame] | 1186 | |
Lingfeng Yang | fe2a31d | 2016-12-02 08:02:15 -0800 | [diff] [blame] | 1187 | bool has_client_vertex_arrays = false; |
| 1188 | bool has_indirect_arrays = false; |
| 1189 | ctx->getVBOUsage(&has_client_vertex_arrays, |
| 1190 | &has_indirect_arrays); |
| 1191 | |
| 1192 | if (has_client_vertex_arrays || |
| 1193 | (!has_client_vertex_arrays && |
| 1194 | !has_indirect_arrays)) { |
| 1195 | ctx->sendVertexAttributes(first, count, true); |
| 1196 | ctx->m_glDrawArrays_enc(ctx, mode, 0, count); |
| 1197 | } else { |
| 1198 | ctx->sendVertexAttributes(0, count, false); |
| 1199 | ctx->m_glDrawArrays_enc(ctx, mode, first, count); |
| 1200 | } |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1201 | } |
| 1202 | |
| 1203 | |
| 1204 | void GL2Encoder::s_glDrawElements(void *self, GLenum mode, GLsizei count, GLenum type, const void *indices) |
| 1205 | { |
| 1206 | |
| 1207 | GL2Encoder *ctx = (GL2Encoder *)self; |
| 1208 | assert(ctx->m_state != NULL); |
Evan Birenbaum | d51386b | 2016-04-13 12:53:09 -0700 | [diff] [blame] | 1209 | SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM); |
| 1210 | SET_ERROR_IF(count < 0, GL_INVALID_VALUE); |
Yahan Zhou | 4520fc9 | 2016-04-20 16:02:10 -0700 | [diff] [blame] | 1211 | SET_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT), GL_INVALID_ENUM); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 1212 | SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1213 | |
Lingfeng Yang | fe2a31d | 2016-12-02 08:02:15 -0800 | [diff] [blame] | 1214 | bool has_client_vertex_arrays = false; |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1215 | bool has_indirect_arrays = false; |
| 1216 | int nLocations = ctx->m_state->nLocations(); |
Yahan Zhou | 5507c04 | 2016-06-01 17:24:28 -0700 | [diff] [blame] | 1217 | GLintptr offset = 0; |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1218 | |
Lingfeng Yang | fe2a31d | 2016-12-02 08:02:15 -0800 | [diff] [blame] | 1219 | ctx->getVBOUsage(&has_client_vertex_arrays, &has_indirect_arrays); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1220 | |
Lingfeng Yang | fe2a31d | 2016-12-02 08:02:15 -0800 | [diff] [blame] | 1221 | if (!has_client_vertex_arrays && !has_indirect_arrays) { |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 1222 | // ALOGW("glDrawElements: no vertex arrays / buffers bound to the command\n"); |
Evan Birenbaum | 82885a6 | 2016-04-28 12:47:57 -0700 | [diff] [blame] | 1223 | GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER); |
| 1224 | SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1225 | } |
| 1226 | |
Lingfeng Yang | 8e2b6e0 | 2016-10-14 11:20:45 -0700 | [diff] [blame] | 1227 | BufferData* buf = NULL; |
Yahan Zhou | 5507c04 | 2016-06-01 17:24:28 -0700 | [diff] [blame] | 1228 | int minIndex = 0, maxIndex = 0; |
Lingfeng Yang | 8e2b6e0 | 2016-10-14 11:20:45 -0700 | [diff] [blame] | 1229 | |
| 1230 | // For validation/immediate index array purposes, |
| 1231 | // we need the min/max vertex index of the index array. |
| 1232 | // If the VBO != 0, this may not be the first time we have |
| 1233 | // used this particular index buffer. getBufferIndexRange |
| 1234 | // can more quickly get min/max vertex index by |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 1235 | // caching previous results. |
Lingfeng Yang | 8e2b6e0 | 2016-10-14 11:20:45 -0700 | [diff] [blame] | 1236 | if (ctx->m_state->currentIndexVbo() != 0) { |
| 1237 | buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo()); |
| 1238 | offset = (GLintptr)indices; |
| 1239 | indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices); |
| 1240 | ctx->getBufferIndexRange(buf, |
| 1241 | indices, |
| 1242 | type, |
Lingfeng Yang | 1ae9d73 | 2016-12-12 16:17:02 -0800 | [diff] [blame] | 1243 | (size_t)count, |
| 1244 | (size_t)offset, |
Lingfeng Yang | 8e2b6e0 | 2016-10-14 11:20:45 -0700 | [diff] [blame] | 1245 | &minIndex, &maxIndex); |
| 1246 | } else { |
| 1247 | // In this case, the |indices| field holds a real |
| 1248 | // array, so calculate the indices now. They will |
| 1249 | // also be needed to know how much data to |
| 1250 | // transfer to host. |
| 1251 | ctx->calcIndexRange(indices, |
| 1252 | type, |
| 1253 | count, |
| 1254 | &minIndex, |
| 1255 | &maxIndex); |
Yahan Zhou | 5507c04 | 2016-06-01 17:24:28 -0700 | [diff] [blame] | 1256 | } |
| 1257 | |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1258 | bool adjustIndices = true; |
| 1259 | if (ctx->m_state->currentIndexVbo() != 0) { |
Lingfeng Yang | fe2a31d | 2016-12-02 08:02:15 -0800 | [diff] [blame] | 1260 | if (!has_client_vertex_arrays) { |
| 1261 | ctx->sendVertexAttributes(0, maxIndex + 1, false); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1262 | ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo()); |
Yahan Zhou | 5507c04 | 2016-06-01 17:24:28 -0700 | [diff] [blame] | 1263 | ctx->glDrawElementsOffset(ctx, mode, count, type, offset); |
Lingfeng Yang | 8e2b6e0 | 2016-10-14 11:20:45 -0700 | [diff] [blame] | 1264 | ctx->flushDrawCall(); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1265 | adjustIndices = false; |
| 1266 | } else { |
| 1267 | BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo()); |
| 1268 | ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1269 | } |
| 1270 | } |
| 1271 | if (adjustIndices) { |
Lingfeng Yang | 8e2b6e0 | 2016-10-14 11:20:45 -0700 | [diff] [blame] | 1272 | void *adjustedIndices = |
| 1273 | ctx->recenterIndices(indices, |
| 1274 | type, |
| 1275 | count, |
| 1276 | minIndex); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1277 | |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1278 | if (has_indirect_arrays || 1) { |
Lingfeng Yang | fe2a31d | 2016-12-02 08:02:15 -0800 | [diff] [blame] | 1279 | ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1, true); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1280 | ctx->glDrawElementsData(ctx, mode, count, type, adjustedIndices, |
| 1281 | count * glSizeof(type)); |
| 1282 | // XXX - OPTIMIZATION (see the other else branch) should be implemented |
| 1283 | if(!has_indirect_arrays) { |
| 1284 | //ALOGD("unoptimized drawelements !!!\n"); |
| 1285 | } |
| 1286 | } else { |
| 1287 | // we are all direct arrays and immidate mode index array - |
| 1288 | // rebuild the arrays and the index array; |
| 1289 | ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n"); |
| 1290 | } |
| 1291 | } |
| 1292 | } |
| 1293 | |
| 1294 | |
| 1295 | GLint * GL2Encoder::getCompressedTextureFormats() |
| 1296 | { |
| 1297 | if (m_compressedTextureFormats == NULL) { |
| 1298 | this->glGetIntegerv(this, GL_NUM_COMPRESSED_TEXTURE_FORMATS, |
| 1299 | &m_num_compressedTextureFormats); |
| 1300 | if (m_num_compressedTextureFormats > 0) { |
| 1301 | // get number of texture formats; |
| 1302 | m_compressedTextureFormats = new GLint[m_num_compressedTextureFormats]; |
| 1303 | this->glGetCompressedTextureFormats(this, m_num_compressedTextureFormats, m_compressedTextureFormats); |
| 1304 | } |
| 1305 | } |
| 1306 | return m_compressedTextureFormats; |
| 1307 | } |
| 1308 | |
| 1309 | // Replace uses of samplerExternalOES with sampler2D, recording the names of |
| 1310 | // modified shaders in data. Also remove |
| 1311 | // #extension GL_OES_EGL_image_external : require |
| 1312 | // statements. |
| 1313 | // |
| 1314 | // This implementation assumes the input has already been pre-processed. If not, |
| 1315 | // a few cases will be mishandled: |
| 1316 | // |
| 1317 | // 1. "mySampler" will be incorrectly recorded as being a samplerExternalOES in |
| 1318 | // the following code: |
| 1319 | // #if 1 |
| 1320 | // uniform sampler2D mySampler; |
| 1321 | // #else |
| 1322 | // uniform samplerExternalOES mySampler; |
| 1323 | // #endif |
| 1324 | // |
| 1325 | // 2. Comments that look like sampler declarations will be incorrectly modified |
| 1326 | // and recorded: |
| 1327 | // // samplerExternalOES hahaFooledYou |
| 1328 | // |
| 1329 | // 3. However, GLSL ES does not have a concatentation operator, so things like |
| 1330 | // this (valid in C) are invalid and not a problem: |
| 1331 | // #define SAMPLER(TYPE, NAME) uniform sampler#TYPE NAME |
| 1332 | // SAMPLER(ExternalOES, mySampler); |
| 1333 | // |
Lingfeng Yang | cc22a7a | 2018-05-15 12:15:57 -0700 | [diff] [blame] | 1334 | |
| 1335 | static const char STR_SAMPLER_EXTERNAL_OES[] = "samplerExternalOES"; |
| 1336 | static const char STR_SAMPLER2D_SPACE[] = "sampler2D "; |
| 1337 | static const char STR_DEFINE[] = "#define"; |
| 1338 | |
| 1339 | static std::vector<std::string> getSamplerExternalAliases(char* str) { |
| 1340 | std::vector<std::string> res; |
| 1341 | |
| 1342 | res.push_back(STR_SAMPLER_EXTERNAL_OES); |
| 1343 | |
| 1344 | // -- capture #define x samplerExternalOES |
| 1345 | char* c = str; |
| 1346 | while ((c = strstr(c, STR_DEFINE))) { |
| 1347 | // Don't push it if samplerExternalOES is not even there. |
| 1348 | char* samplerExternalOES_next = strstr(c, STR_SAMPLER_EXTERNAL_OES); |
| 1349 | if (!samplerExternalOES_next) break; |
| 1350 | |
| 1351 | bool prevIdent = false; |
| 1352 | |
| 1353 | std::vector<std::string> idents; |
| 1354 | std::string curr; |
| 1355 | |
| 1356 | while (*c != '\0') { |
| 1357 | |
| 1358 | if (isspace(*c)) { |
| 1359 | if (prevIdent) { |
| 1360 | idents.push_back(curr); |
| 1361 | curr = ""; |
| 1362 | } |
| 1363 | } |
| 1364 | |
| 1365 | if (*c == '\n' || idents.size() == 3) break; |
| 1366 | |
| 1367 | if (isalpha(*c) || *c == '_') { |
| 1368 | curr.push_back(*c); |
| 1369 | prevIdent = true; |
| 1370 | } |
| 1371 | |
| 1372 | ++c; |
| 1373 | } |
| 1374 | |
| 1375 | if (idents.size() != 3) continue; |
| 1376 | |
| 1377 | const std::string& defineLhs = idents[1]; |
| 1378 | const std::string& defineRhs = idents[2]; |
| 1379 | |
| 1380 | if (defineRhs == STR_SAMPLER_EXTERNAL_OES) { |
| 1381 | res.push_back(defineLhs); |
| 1382 | } |
| 1383 | |
| 1384 | if (*c == '\0') break; |
| 1385 | } |
| 1386 | |
| 1387 | return res; |
| 1388 | } |
| 1389 | |
| 1390 | static bool replaceExternalSamplerUniformDefinition(char* str, const std::string& samplerExternalType, ShaderData* data) { |
| 1391 | // -- replace "samplerExternalOES" with "sampler2D" and record name |
| 1392 | char* c = str; |
| 1393 | while ((c = strstr(c, samplerExternalType.c_str()))) { |
| 1394 | // Make sure "samplerExternalOES" isn't a substring of a larger token |
| 1395 | if (c == str || !isspace(*(c-1))) { |
| 1396 | c++; |
| 1397 | continue; |
| 1398 | } |
| 1399 | char* sampler_start = c; |
| 1400 | c += samplerExternalType.size(); |
| 1401 | if (!isspace(*c) && *c != '\0') { |
| 1402 | continue; |
| 1403 | } |
| 1404 | |
| 1405 | // capture sampler name |
| 1406 | while (isspace(*c) && *c != '\0') { |
| 1407 | c++; |
| 1408 | } |
| 1409 | if (!isalpha(*c) && *c != '_') { |
| 1410 | // not an identifier |
| 1411 | return false; |
| 1412 | } |
| 1413 | char* name_start = c; |
| 1414 | do { |
| 1415 | c++; |
| 1416 | } while (isalnum(*c) || *c == '_'); |
| 1417 | data->samplerExternalNames.push_back( |
| 1418 | android::String8(name_start, c - name_start)); |
| 1419 | |
| 1420 | // We only need to perform a string replacement for the original |
| 1421 | // occurrence of samplerExternalOES if a #define was used. |
| 1422 | // |
| 1423 | // The important part was to record the name in |
| 1424 | // |data->samplerExternalNames|. |
| 1425 | if (samplerExternalType == STR_SAMPLER_EXTERNAL_OES) { |
| 1426 | memcpy(sampler_start, STR_SAMPLER2D_SPACE, sizeof(STR_SAMPLER2D_SPACE)-1); |
| 1427 | } |
| 1428 | } |
| 1429 | |
| 1430 | return true; |
| 1431 | } |
| 1432 | |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1433 | static bool replaceSamplerExternalWith2D(char* const str, ShaderData* const data) |
| 1434 | { |
| 1435 | static const char STR_HASH_EXTENSION[] = "#extension"; |
| 1436 | static const char STR_GL_OES_EGL_IMAGE_EXTERNAL[] = "GL_OES_EGL_image_external"; |
Lingfeng Yang | 3546c4d | 2018-04-10 12:34:30 -0700 | [diff] [blame] | 1437 | static const char STR_GL_OES_EGL_IMAGE_EXTERNAL_ESSL3[] = "GL_OES_EGL_image_external_essl3"; |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1438 | |
| 1439 | // -- overwrite all "#extension GL_OES_EGL_image_external : xxx" statements |
| 1440 | char* c = str; |
| 1441 | while ((c = strstr(c, STR_HASH_EXTENSION))) { |
| 1442 | char* start = c; |
| 1443 | c += sizeof(STR_HASH_EXTENSION)-1; |
| 1444 | while (isspace(*c) && *c != '\0') { |
| 1445 | c++; |
| 1446 | } |
Lingfeng Yang | 3546c4d | 2018-04-10 12:34:30 -0700 | [diff] [blame] | 1447 | |
| 1448 | bool hasBaseImageExternal = |
| 1449 | !strncmp(c, STR_GL_OES_EGL_IMAGE_EXTERNAL, |
| 1450 | sizeof(STR_GL_OES_EGL_IMAGE_EXTERNAL) - 1); |
| 1451 | bool hasEssl3ImageExternal = |
| 1452 | !strncmp(c, STR_GL_OES_EGL_IMAGE_EXTERNAL_ESSL3, |
| 1453 | sizeof(STR_GL_OES_EGL_IMAGE_EXTERNAL_ESSL3) - 1); |
| 1454 | |
| 1455 | if (hasBaseImageExternal || hasEssl3ImageExternal) |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1456 | { |
| 1457 | // #extension statements are terminated by end of line |
| 1458 | c = start; |
| 1459 | while (*c != '\0' && *c != '\r' && *c != '\n') { |
| 1460 | *c++ = ' '; |
| 1461 | } |
| 1462 | } |
| 1463 | } |
| 1464 | |
Lingfeng Yang | cc22a7a | 2018-05-15 12:15:57 -0700 | [diff] [blame] | 1465 | std::vector<std::string> samplerExternalAliases = |
| 1466 | getSamplerExternalAliases(str); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1467 | |
Lingfeng Yang | cc22a7a | 2018-05-15 12:15:57 -0700 | [diff] [blame] | 1468 | for (size_t i = 0; i < samplerExternalAliases.size(); i++) { |
| 1469 | if (!replaceExternalSamplerUniformDefinition( |
| 1470 | str, samplerExternalAliases[i], data)) |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1471 | return false; |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1472 | } |
| 1473 | |
| 1474 | return true; |
| 1475 | } |
| 1476 | |
Bo Hu | 73568cd | 2015-01-20 16:29:50 -0800 | [diff] [blame] | 1477 | void GL2Encoder::s_glShaderBinary(void *self, GLsizei n, const GLuint *shaders, GLenum binaryformat, const void* binary, GLsizei length) |
| 1478 | { |
| 1479 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 1480 | // Although it is not supported, need to set proper error code. |
| 1481 | SET_ERROR_IF(1, GL_INVALID_ENUM); |
| 1482 | } |
| 1483 | |
David 'Digit' Turner | 02fdb69 | 2014-10-30 18:07:56 +0100 | [diff] [blame] | 1484 | void GL2Encoder::s_glShaderSource(void *self, GLuint shader, GLsizei count, const GLchar * const *string, const GLint *length) |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1485 | { |
| 1486 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 1487 | ShaderData* shaderData = ctx->m_shared->getShaderData(shader); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 1488 | SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(shader), GL_INVALID_VALUE); |
Tina Zhang | 7a84f65 | 2014-12-04 12:37:30 +0800 | [diff] [blame] | 1489 | SET_ERROR_IF(!shaderData, GL_INVALID_OPERATION); |
| 1490 | SET_ERROR_IF((count<0), GL_INVALID_VALUE); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1491 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 1492 | // Track original sources---they may be translated in the backend |
| 1493 | std::vector<std::string> orig_sources; |
| 1494 | for (int i = 0; i < count; i++) { |
| 1495 | orig_sources.push_back(std::string((const char*)(string[i]))); |
| 1496 | } |
| 1497 | shaderData->sources = orig_sources; |
| 1498 | |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1499 | int len = glUtilsCalcShaderSourceLen((char**)string, (GLint*)length, count); |
| 1500 | char *str = new char[len + 1]; |
| 1501 | glUtilsPackStrings(str, (char**)string, (GLint*)length, count); |
| 1502 | |
| 1503 | // TODO: pre-process str before calling replaceSamplerExternalWith2D(). |
| 1504 | // Perhaps we can borrow Mesa's pre-processor? |
| 1505 | |
| 1506 | if (!replaceSamplerExternalWith2D(str, shaderData)) { |
Adam Buchbinder | 9ae1469 | 2016-05-20 15:25:59 -0700 | [diff] [blame] | 1507 | delete[] str; |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1508 | ctx->setError(GL_OUT_OF_MEMORY); |
| 1509 | return; |
| 1510 | } |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1511 | ctx->glShaderString(ctx, shader, str, len + 1); |
Adam Buchbinder | 9ae1469 | 2016-05-20 15:25:59 -0700 | [diff] [blame] | 1512 | delete[] str; |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1513 | } |
| 1514 | |
| 1515 | void GL2Encoder::s_glFinish(void *self) |
| 1516 | { |
| 1517 | GL2Encoder *ctx = (GL2Encoder *)self; |
| 1518 | ctx->glFinishRoundTrip(self); |
| 1519 | } |
| 1520 | |
| 1521 | void GL2Encoder::s_glLinkProgram(void * self, GLuint program) |
| 1522 | { |
| 1523 | GL2Encoder *ctx = (GL2Encoder *)self; |
Yahan Zhou | b99406c | 2016-11-22 14:03:56 -0800 | [diff] [blame] | 1524 | bool isProgram = ctx->m_shared->isProgram(program); |
| 1525 | SET_ERROR_IF(!isProgram && !ctx->m_shared->isShader(program), GL_INVALID_VALUE); |
| 1526 | SET_ERROR_IF(!isProgram, GL_INVALID_OPERATION); |
| 1527 | |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1528 | ctx->m_glLinkProgram_enc(self, program); |
| 1529 | |
| 1530 | GLint linkStatus = 0; |
Lingfeng Yang | 80a3633 | 2017-07-09 10:58:07 -0700 | [diff] [blame] | 1531 | ctx->glGetProgramiv(self, program, GL_LINK_STATUS, &linkStatus); |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 1532 | if (!linkStatus) { |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1533 | return; |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 1534 | } |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1535 | |
| 1536 | //get number of active uniforms in the program |
| 1537 | GLint numUniforms=0; |
| 1538 | ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORMS, &numUniforms); |
| 1539 | ctx->m_shared->initProgramData(program,numUniforms); |
| 1540 | |
| 1541 | //get the length of the longest uniform name |
| 1542 | GLint maxLength=0; |
| 1543 | ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength); |
| 1544 | |
| 1545 | GLint size; |
| 1546 | GLenum type; |
| 1547 | GLchar *name = new GLchar[maxLength+1]; |
| 1548 | GLint location; |
| 1549 | //for each active uniform, get its size and starting location. |
| 1550 | for (GLint i=0 ; i<numUniforms ; ++i) |
| 1551 | { |
| 1552 | ctx->glGetActiveUniform(self, program, i, maxLength, NULL, &size, &type, name); |
| 1553 | location = ctx->m_glGetUniformLocation_enc(self, program, name); |
| 1554 | ctx->m_shared->setProgramIndexInfo(program, i, location, size, type, name); |
| 1555 | } |
| 1556 | ctx->m_shared->setupLocationShiftWAR(program); |
| 1557 | |
| 1558 | delete[] name; |
| 1559 | } |
| 1560 | |
| 1561 | void GL2Encoder::s_glDeleteProgram(void *self, GLuint program) |
| 1562 | { |
| 1563 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 1564 | ctx->m_glDeleteProgram_enc(self, program); |
| 1565 | |
| 1566 | ctx->m_shared->deleteProgramData(program); |
| 1567 | } |
| 1568 | |
| 1569 | void GL2Encoder::s_glGetUniformiv(void *self, GLuint program, GLint location, GLint* params) |
| 1570 | { |
| 1571 | GL2Encoder *ctx = (GL2Encoder*)self; |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 1572 | SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(program), GL_INVALID_VALUE); |
Lingfeng Yang | 35b0fda | 2016-04-08 12:21:13 -0700 | [diff] [blame] | 1573 | SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1574 | SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION); |
| 1575 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location); |
| 1576 | SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION); |
| 1577 | ctx->m_glGetUniformiv_enc(self, program, hostLoc, params); |
| 1578 | } |
| 1579 | void GL2Encoder::s_glGetUniformfv(void *self, GLuint program, GLint location, GLfloat* params) |
| 1580 | { |
| 1581 | GL2Encoder *ctx = (GL2Encoder*)self; |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 1582 | SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(program), GL_INVALID_VALUE); |
Lingfeng Yang | 35b0fda | 2016-04-08 12:21:13 -0700 | [diff] [blame] | 1583 | SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1584 | SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION); |
| 1585 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(program,location); |
| 1586 | SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION); |
| 1587 | ctx->m_glGetUniformfv_enc(self, program, hostLoc, params); |
| 1588 | } |
| 1589 | |
| 1590 | GLuint GL2Encoder::s_glCreateProgram(void * self) |
| 1591 | { |
| 1592 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 1593 | GLuint program = ctx->m_glCreateProgram_enc(self); |
| 1594 | if (program!=0) |
| 1595 | ctx->m_shared->addProgramData(program); |
| 1596 | return program; |
| 1597 | } |
| 1598 | |
| 1599 | GLuint GL2Encoder::s_glCreateShader(void *self, GLenum shaderType) |
| 1600 | { |
| 1601 | GL2Encoder *ctx = (GL2Encoder*)self; |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 1602 | RET_AND_SET_ERROR_IF(!GLESv2Validation::shaderType(ctx, shaderType), GL_INVALID_ENUM, 0); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1603 | GLuint shader = ctx->m_glCreateShader_enc(self, shaderType); |
| 1604 | if (shader != 0) { |
| 1605 | if (!ctx->m_shared->addShaderData(shader)) { |
| 1606 | ctx->m_glDeleteShader_enc(self, shader); |
| 1607 | return 0; |
| 1608 | } |
| 1609 | } |
| 1610 | return shader; |
| 1611 | } |
| 1612 | |
bohu | 56bf82f | 2014-10-17 15:35:48 -0700 | [diff] [blame] | 1613 | void GL2Encoder::s_glGetAttachedShaders(void *self, GLuint program, GLsizei maxCount, |
| 1614 | GLsizei* count, GLuint* shaders) |
| 1615 | { |
| 1616 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 1617 | SET_ERROR_IF(maxCount < 0, GL_INVALID_VALUE); |
| 1618 | ctx->m_glGetAttachedShaders_enc(self, program, maxCount, count, shaders); |
| 1619 | } |
| 1620 | |
| 1621 | void GL2Encoder::s_glGetShaderSource(void *self, GLuint shader, GLsizei bufsize, |
| 1622 | GLsizei* length, GLchar* source) |
| 1623 | { |
| 1624 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 1625 | SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE); |
| 1626 | ctx->m_glGetShaderSource_enc(self, shader, bufsize, length, source); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 1627 | ShaderData* shaderData = ctx->m_shared->getShaderData(shader); |
| 1628 | if (shaderData) { |
| 1629 | std::string returned; |
| 1630 | int curr_len = 0; |
| 1631 | for (int i = 0; i < shaderData->sources.size(); i++) { |
| 1632 | if (curr_len + shaderData->sources[i].size() < bufsize - 1) { |
| 1633 | returned += shaderData->sources[i]; |
| 1634 | } else { |
| 1635 | returned += shaderData->sources[i].substr(0, bufsize - 1 - curr_len); |
| 1636 | break; |
| 1637 | } |
| 1638 | } |
| 1639 | memcpy(source, returned.substr(0, bufsize - 1).c_str(), bufsize); |
| 1640 | } |
bohu | 56bf82f | 2014-10-17 15:35:48 -0700 | [diff] [blame] | 1641 | } |
| 1642 | |
| 1643 | void GL2Encoder::s_glGetShaderInfoLog(void *self, GLuint shader, GLsizei bufsize, |
| 1644 | GLsizei* length, GLchar* infolog) |
| 1645 | { |
| 1646 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 1647 | SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE); |
| 1648 | ctx->m_glGetShaderInfoLog_enc(self, shader, bufsize, length, infolog); |
| 1649 | } |
| 1650 | |
| 1651 | void GL2Encoder::s_glGetProgramInfoLog(void *self, GLuint program, GLsizei bufsize, |
| 1652 | GLsizei* length, GLchar* infolog) |
| 1653 | { |
| 1654 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 1655 | SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE); |
| 1656 | ctx->m_glGetProgramInfoLog_enc(self, program, bufsize, length, infolog); |
| 1657 | } |
| 1658 | |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1659 | void GL2Encoder::s_glDeleteShader(void *self, GLenum shader) |
| 1660 | { |
| 1661 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 1662 | ctx->m_glDeleteShader_enc(self,shader); |
| 1663 | ctx->m_shared->unrefShaderData(shader); |
| 1664 | } |
| 1665 | |
| 1666 | void GL2Encoder::s_glAttachShader(void *self, GLuint program, GLuint shader) |
| 1667 | { |
| 1668 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 1669 | ctx->m_glAttachShader_enc(self, program, shader); |
| 1670 | ctx->m_shared->attachShader(program, shader); |
| 1671 | } |
| 1672 | |
| 1673 | void GL2Encoder::s_glDetachShader(void *self, GLuint program, GLuint shader) |
| 1674 | { |
| 1675 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 1676 | ctx->m_glDetachShader_enc(self, program, shader); |
| 1677 | ctx->m_shared->detachShader(program, shader); |
| 1678 | } |
| 1679 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 1680 | int sArrIndexOfUniformExpr(const char* name, int* err) { |
| 1681 | *err = 0; |
| 1682 | int arrIndex = 0; |
| 1683 | int namelen = strlen(name); |
| 1684 | if (name[namelen-1] == ']') { |
| 1685 | const char *brace = strrchr(name,'['); |
| 1686 | if (!brace || sscanf(brace+1,"%d",&arrIndex) != 1) { |
| 1687 | *err = 1; return 0; |
| 1688 | } |
| 1689 | } |
| 1690 | return arrIndex; |
| 1691 | } |
| 1692 | |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1693 | int GL2Encoder::s_glGetUniformLocation(void *self, GLuint program, const GLchar *name) |
| 1694 | { |
| 1695 | if (!name) return -1; |
| 1696 | |
| 1697 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 1698 | |
| 1699 | // if we need the uniform location WAR |
| 1700 | // parse array index from the end of the name string |
| 1701 | int arrIndex = 0; |
| 1702 | bool needLocationWAR = ctx->m_shared->needUniformLocationWAR(program); |
| 1703 | if (needLocationWAR) { |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 1704 | int err; |
| 1705 | arrIndex = sArrIndexOfUniformExpr(name, &err); |
| 1706 | if (err) return -1; |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1707 | } |
| 1708 | |
| 1709 | int hostLoc = ctx->m_glGetUniformLocation_enc(self, program, name); |
| 1710 | if (hostLoc >= 0 && needLocationWAR) { |
| 1711 | return ctx->m_shared->locationWARHostToApp(program, hostLoc, arrIndex); |
| 1712 | } |
| 1713 | return hostLoc; |
| 1714 | } |
| 1715 | |
| 1716 | bool GL2Encoder::updateHostTexture2DBinding(GLenum texUnit, GLenum newTarget) |
| 1717 | { |
| 1718 | if (newTarget != GL_TEXTURE_2D && newTarget != GL_TEXTURE_EXTERNAL_OES) |
| 1719 | return false; |
| 1720 | |
| 1721 | m_state->setActiveTextureUnit(texUnit); |
| 1722 | |
| 1723 | GLenum oldTarget = m_state->getPriorityEnabledTarget(GL_TEXTURE_2D); |
| 1724 | if (newTarget != oldTarget) { |
| 1725 | if (newTarget == GL_TEXTURE_EXTERNAL_OES) { |
| 1726 | m_state->disableTextureTarget(GL_TEXTURE_2D); |
| 1727 | m_state->enableTextureTarget(GL_TEXTURE_EXTERNAL_OES); |
| 1728 | } else { |
| 1729 | m_state->disableTextureTarget(GL_TEXTURE_EXTERNAL_OES); |
| 1730 | m_state->enableTextureTarget(GL_TEXTURE_2D); |
| 1731 | } |
| 1732 | m_glActiveTexture_enc(this, texUnit); |
| 1733 | m_glBindTexture_enc(this, GL_TEXTURE_2D, |
| 1734 | m_state->getBoundTexture(newTarget)); |
| 1735 | return true; |
| 1736 | } |
| 1737 | |
| 1738 | return false; |
| 1739 | } |
| 1740 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 1741 | void GL2Encoder::updateHostTexture2DBindingsFromProgramData(GLuint program) { |
| 1742 | GL2Encoder *ctx = this; |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1743 | GLClientState* state = ctx->m_state; |
| 1744 | GLSharedGroupPtr shared = ctx->m_shared; |
| 1745 | |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1746 | GLenum origActiveTexture = state->getActiveTextureUnit(); |
| 1747 | GLenum hostActiveTexture = origActiveTexture; |
| 1748 | GLint samplerIdx = -1; |
| 1749 | GLint samplerVal; |
| 1750 | GLenum samplerTarget; |
| 1751 | while ((samplerIdx = shared->getNextSamplerUniform(program, samplerIdx, &samplerVal, &samplerTarget)) != -1) { |
| 1752 | if (samplerVal < 0 || samplerVal >= GLClientState::MAX_TEXTURE_UNITS) |
| 1753 | continue; |
| 1754 | if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + samplerVal, |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 1755 | samplerTarget)) |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1756 | { |
| 1757 | hostActiveTexture = GL_TEXTURE0 + samplerVal; |
| 1758 | } |
| 1759 | } |
| 1760 | state->setActiveTextureUnit(origActiveTexture); |
| 1761 | if (hostActiveTexture != origActiveTexture) { |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 1762 | ctx->m_glActiveTexture_enc(ctx, origActiveTexture); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1763 | } |
| 1764 | } |
| 1765 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 1766 | void GL2Encoder::s_glUseProgram(void *self, GLuint program) |
| 1767 | { |
| 1768 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 1769 | GLSharedGroupPtr shared = ctx->m_shared; |
| 1770 | |
| 1771 | SET_ERROR_IF(program && !shared->isShaderOrProgramObject(program), GL_INVALID_VALUE); |
| 1772 | SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION); |
| 1773 | |
| 1774 | ctx->m_glUseProgram_enc(self, program); |
| 1775 | ctx->m_state->setCurrentProgram(program); |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 1776 | ctx->m_state->setCurrentShaderProgram(program); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 1777 | |
| 1778 | ctx->updateHostTexture2DBindingsFromProgramData(program); |
| 1779 | } |
| 1780 | |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1781 | void GL2Encoder::s_glUniform1f(void *self , GLint location, GLfloat x) |
| 1782 | { |
| 1783 | GL2Encoder *ctx = (GL2Encoder*)self; |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 1784 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1785 | ctx->m_glUniform1f_enc(self, hostLoc, x); |
| 1786 | } |
| 1787 | |
| 1788 | void GL2Encoder::s_glUniform1fv(void *self , GLint location, GLsizei count, const GLfloat* v) |
| 1789 | { |
| 1790 | GL2Encoder *ctx = (GL2Encoder*)self; |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 1791 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1792 | ctx->m_glUniform1fv_enc(self, hostLoc, count, v); |
| 1793 | } |
| 1794 | |
| 1795 | void GL2Encoder::s_glUniform1i(void *self , GLint location, GLint x) |
| 1796 | { |
| 1797 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 1798 | GLClientState* state = ctx->m_state; |
| 1799 | GLSharedGroupPtr shared = ctx->m_shared; |
| 1800 | |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 1801 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1802 | ctx->m_glUniform1i_enc(self, hostLoc, x); |
| 1803 | |
| 1804 | GLenum target; |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 1805 | if (shared->setSamplerUniform(state->currentShaderProgram(), location, x, &target)) { |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1806 | GLenum origActiveTexture = state->getActiveTextureUnit(); |
| 1807 | if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + x, target)) { |
| 1808 | ctx->m_glActiveTexture_enc(self, origActiveTexture); |
| 1809 | } |
| 1810 | state->setActiveTextureUnit(origActiveTexture); |
| 1811 | } |
| 1812 | } |
| 1813 | |
| 1814 | void GL2Encoder::s_glUniform1iv(void *self , GLint location, GLsizei count, const GLint* v) |
| 1815 | { |
| 1816 | GL2Encoder *ctx = (GL2Encoder*)self; |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 1817 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1818 | ctx->m_glUniform1iv_enc(self, hostLoc, count, v); |
| 1819 | } |
| 1820 | |
| 1821 | void GL2Encoder::s_glUniform2f(void *self , GLint location, GLfloat x, GLfloat y) |
| 1822 | { |
| 1823 | GL2Encoder *ctx = (GL2Encoder*)self; |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 1824 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1825 | ctx->m_glUniform2f_enc(self, hostLoc, x, y); |
| 1826 | } |
| 1827 | |
| 1828 | void GL2Encoder::s_glUniform2fv(void *self , GLint location, GLsizei count, const GLfloat* v) |
| 1829 | { |
| 1830 | GL2Encoder *ctx = (GL2Encoder*)self; |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 1831 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1832 | ctx->m_glUniform2fv_enc(self, hostLoc, count, v); |
| 1833 | } |
| 1834 | |
| 1835 | void GL2Encoder::s_glUniform2i(void *self , GLint location, GLint x, GLint y) |
| 1836 | { |
| 1837 | GL2Encoder *ctx = (GL2Encoder*)self; |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 1838 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1839 | ctx->m_glUniform2i_enc(self, hostLoc, x, y); |
| 1840 | } |
| 1841 | |
| 1842 | void GL2Encoder::s_glUniform2iv(void *self , GLint location, GLsizei count, const GLint* v) |
| 1843 | { |
| 1844 | GL2Encoder *ctx = (GL2Encoder*)self; |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 1845 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1846 | ctx->m_glUniform2iv_enc(self, hostLoc, count, v); |
| 1847 | } |
| 1848 | |
| 1849 | void GL2Encoder::s_glUniform3f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z) |
| 1850 | { |
| 1851 | GL2Encoder *ctx = (GL2Encoder*)self; |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 1852 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1853 | ctx->m_glUniform3f_enc(self, hostLoc, x, y, z); |
| 1854 | } |
| 1855 | |
| 1856 | void GL2Encoder::s_glUniform3fv(void *self , GLint location, GLsizei count, const GLfloat* v) |
| 1857 | { |
| 1858 | GL2Encoder *ctx = (GL2Encoder*)self; |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 1859 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1860 | ctx->m_glUniform3fv_enc(self, hostLoc, count, v); |
| 1861 | } |
| 1862 | |
| 1863 | void GL2Encoder::s_glUniform3i(void *self , GLint location, GLint x, GLint y, GLint z) |
| 1864 | { |
| 1865 | GL2Encoder *ctx = (GL2Encoder*)self; |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 1866 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1867 | ctx->m_glUniform3i_enc(self, hostLoc, x, y, z); |
| 1868 | } |
| 1869 | |
| 1870 | void GL2Encoder::s_glUniform3iv(void *self , GLint location, GLsizei count, const GLint* v) |
| 1871 | { |
| 1872 | GL2Encoder *ctx = (GL2Encoder*)self; |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 1873 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1874 | ctx->m_glUniform3iv_enc(self, hostLoc, count, v); |
| 1875 | } |
| 1876 | |
| 1877 | void GL2Encoder::s_glUniform4f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) |
| 1878 | { |
| 1879 | GL2Encoder *ctx = (GL2Encoder*)self; |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 1880 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1881 | ctx->m_glUniform4f_enc(self, hostLoc, x, y, z, w); |
| 1882 | } |
| 1883 | |
| 1884 | void GL2Encoder::s_glUniform4fv(void *self , GLint location, GLsizei count, const GLfloat* v) |
| 1885 | { |
| 1886 | GL2Encoder *ctx = (GL2Encoder*)self; |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 1887 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1888 | ctx->m_glUniform4fv_enc(self, hostLoc, count, v); |
| 1889 | } |
| 1890 | |
| 1891 | void GL2Encoder::s_glUniform4i(void *self , GLint location, GLint x, GLint y, GLint z, GLint w) |
| 1892 | { |
| 1893 | GL2Encoder *ctx = (GL2Encoder*)self; |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 1894 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1895 | ctx->m_glUniform4i_enc(self, hostLoc, x, y, z, w); |
| 1896 | } |
| 1897 | |
| 1898 | void GL2Encoder::s_glUniform4iv(void *self , GLint location, GLsizei count, const GLint* v) |
| 1899 | { |
| 1900 | GL2Encoder *ctx = (GL2Encoder*)self; |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 1901 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1902 | ctx->m_glUniform4iv_enc(self, hostLoc, count, v); |
| 1903 | } |
| 1904 | |
| 1905 | void GL2Encoder::s_glUniformMatrix2fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) |
| 1906 | { |
| 1907 | GL2Encoder *ctx = (GL2Encoder*)self; |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 1908 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1909 | ctx->m_glUniformMatrix2fv_enc(self, hostLoc, count, transpose, value); |
| 1910 | } |
| 1911 | |
| 1912 | void GL2Encoder::s_glUniformMatrix3fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) |
| 1913 | { |
| 1914 | GL2Encoder *ctx = (GL2Encoder*)self; |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 1915 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1916 | ctx->m_glUniformMatrix3fv_enc(self, hostLoc, count, transpose, value); |
| 1917 | } |
| 1918 | |
| 1919 | void GL2Encoder::s_glUniformMatrix4fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) |
| 1920 | { |
| 1921 | GL2Encoder *ctx = (GL2Encoder*)self; |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 1922 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1923 | ctx->m_glUniformMatrix4fv_enc(self, hostLoc, count, transpose, value); |
| 1924 | } |
| 1925 | |
| 1926 | void GL2Encoder::s_glActiveTexture(void* self, GLenum texture) |
| 1927 | { |
| 1928 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 1929 | GLClientState* state = ctx->m_state; |
| 1930 | GLenum err; |
| 1931 | |
| 1932 | SET_ERROR_IF((err = state->setActiveTextureUnit(texture)) != GL_NO_ERROR, err); |
| 1933 | |
| 1934 | ctx->m_glActiveTexture_enc(ctx, texture); |
| 1935 | } |
| 1936 | |
| 1937 | void GL2Encoder::s_glBindTexture(void* self, GLenum target, GLuint texture) |
| 1938 | { |
| 1939 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 1940 | GLClientState* state = ctx->m_state; |
| 1941 | GLenum err; |
| 1942 | GLboolean firstUse; |
| 1943 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 1944 | SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1945 | SET_ERROR_IF((err = state->bindTexture(target, texture, &firstUse)) != GL_NO_ERROR, err); |
| 1946 | |
| 1947 | if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES) { |
| 1948 | ctx->m_glBindTexture_enc(ctx, target, texture); |
| 1949 | return; |
| 1950 | } |
| 1951 | |
| 1952 | GLenum priorityTarget = state->getPriorityEnabledTarget(GL_TEXTURE_2D); |
| 1953 | |
| 1954 | if (target == GL_TEXTURE_EXTERNAL_OES && firstUse) { |
| 1955 | ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture); |
| 1956 | ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, |
| 1957 | GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| 1958 | ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, |
| 1959 | GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| 1960 | ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, |
| 1961 | GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| 1962 | |
| 1963 | if (target != priorityTarget) { |
| 1964 | ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, |
| 1965 | state->getBoundTexture(GL_TEXTURE_2D)); |
| 1966 | } |
| 1967 | } |
| 1968 | |
| 1969 | if (target == priorityTarget) { |
| 1970 | ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture); |
| 1971 | } |
| 1972 | } |
| 1973 | |
| 1974 | void GL2Encoder::s_glDeleteTextures(void* self, GLsizei n, const GLuint* textures) |
| 1975 | { |
| 1976 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 1977 | GLClientState* state = ctx->m_state; |
| 1978 | |
| 1979 | state->deleteTextures(n, textures); |
| 1980 | ctx->m_glDeleteTextures_enc(ctx, n, textures); |
| 1981 | } |
| 1982 | |
| 1983 | void GL2Encoder::s_glGetTexParameterfv(void* self, |
| 1984 | GLenum target, GLenum pname, GLfloat* params) |
| 1985 | { |
| 1986 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 1987 | const GLClientState* state = ctx->m_state; |
| 1988 | |
| 1989 | if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { |
| 1990 | ctx->override2DTextureTarget(target); |
| 1991 | ctx->m_glGetTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params); |
Lingfeng Yang | b5c03d5 | 2016-09-07 14:40:03 -0700 | [diff] [blame] | 1992 | ctx->restore2DTextureTarget(target); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 1993 | } else { |
| 1994 | ctx->m_glGetTexParameterfv_enc(ctx, target, pname, params); |
| 1995 | } |
| 1996 | } |
| 1997 | |
| 1998 | void GL2Encoder::s_glGetTexParameteriv(void* self, |
| 1999 | GLenum target, GLenum pname, GLint* params) |
| 2000 | { |
| 2001 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 2002 | const GLClientState* state = ctx->m_state; |
| 2003 | |
| 2004 | switch (pname) { |
| 2005 | case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES: |
| 2006 | *params = 1; |
| 2007 | break; |
| 2008 | |
| 2009 | default: |
| 2010 | if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { |
| 2011 | ctx->override2DTextureTarget(target); |
| 2012 | ctx->m_glGetTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params); |
Lingfeng Yang | b5c03d5 | 2016-09-07 14:40:03 -0700 | [diff] [blame] | 2013 | ctx->restore2DTextureTarget(target); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 2014 | } else { |
| 2015 | ctx->m_glGetTexParameteriv_enc(ctx, target, pname, params); |
| 2016 | } |
| 2017 | break; |
| 2018 | } |
| 2019 | } |
| 2020 | |
| 2021 | static bool isValidTextureExternalParam(GLenum pname, GLenum param) |
| 2022 | { |
| 2023 | switch (pname) { |
| 2024 | case GL_TEXTURE_MIN_FILTER: |
| 2025 | case GL_TEXTURE_MAG_FILTER: |
| 2026 | return param == GL_NEAREST || param == GL_LINEAR; |
| 2027 | |
| 2028 | case GL_TEXTURE_WRAP_S: |
| 2029 | case GL_TEXTURE_WRAP_T: |
| 2030 | return param == GL_CLAMP_TO_EDGE; |
| 2031 | |
| 2032 | default: |
| 2033 | return true; |
| 2034 | } |
| 2035 | } |
| 2036 | |
| 2037 | void GL2Encoder::s_glTexParameterf(void* self, |
| 2038 | GLenum target, GLenum pname, GLfloat param) |
| 2039 | { |
| 2040 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 2041 | const GLClientState* state = ctx->m_state; |
| 2042 | |
| 2043 | SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES && |
| 2044 | !isValidTextureExternalParam(pname, (GLenum)param)), |
| 2045 | GL_INVALID_ENUM); |
| 2046 | |
| 2047 | if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { |
| 2048 | ctx->override2DTextureTarget(target); |
| 2049 | ctx->m_glTexParameterf_enc(ctx, GL_TEXTURE_2D, pname, param); |
Lingfeng Yang | b5c03d5 | 2016-09-07 14:40:03 -0700 | [diff] [blame] | 2050 | ctx->restore2DTextureTarget(target); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 2051 | } else { |
| 2052 | ctx->m_glTexParameterf_enc(ctx, target, pname, param); |
| 2053 | } |
| 2054 | } |
| 2055 | |
| 2056 | void GL2Encoder::s_glTexParameterfv(void* self, |
| 2057 | GLenum target, GLenum pname, const GLfloat* params) |
| 2058 | { |
| 2059 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 2060 | const GLClientState* state = ctx->m_state; |
| 2061 | |
| 2062 | SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES && |
| 2063 | !isValidTextureExternalParam(pname, (GLenum)params[0])), |
| 2064 | GL_INVALID_ENUM); |
| 2065 | |
| 2066 | if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { |
| 2067 | ctx->override2DTextureTarget(target); |
| 2068 | ctx->m_glTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params); |
Lingfeng Yang | b5c03d5 | 2016-09-07 14:40:03 -0700 | [diff] [blame] | 2069 | ctx->restore2DTextureTarget(target); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 2070 | } else { |
| 2071 | ctx->m_glTexParameterfv_enc(ctx, target, pname, params); |
| 2072 | } |
| 2073 | } |
| 2074 | |
| 2075 | void GL2Encoder::s_glTexParameteri(void* self, |
| 2076 | GLenum target, GLenum pname, GLint param) |
| 2077 | { |
| 2078 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 2079 | const GLClientState* state = ctx->m_state; |
| 2080 | |
| 2081 | SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES && |
| 2082 | !isValidTextureExternalParam(pname, (GLenum)param)), |
| 2083 | GL_INVALID_ENUM); |
| 2084 | |
| 2085 | if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { |
| 2086 | ctx->override2DTextureTarget(target); |
| 2087 | ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, pname, param); |
Lingfeng Yang | b5c03d5 | 2016-09-07 14:40:03 -0700 | [diff] [blame] | 2088 | ctx->restore2DTextureTarget(target); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 2089 | } else { |
| 2090 | ctx->m_glTexParameteri_enc(ctx, target, pname, param); |
| 2091 | } |
| 2092 | } |
| 2093 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 2094 | static int ilog2(uint32_t x) { |
| 2095 | int p = 0; |
| 2096 | while ((1 << p) < x) |
| 2097 | p++; |
| 2098 | return p; |
| 2099 | } |
| 2100 | |
bohu | 26a9298 | 2014-11-25 16:50:37 -0800 | [diff] [blame] | 2101 | void GL2Encoder::s_glTexImage2D(void* self, GLenum target, GLint level, |
| 2102 | GLint internalformat, GLsizei width, GLsizei height, GLint border, |
| 2103 | GLenum format, GLenum type, const GLvoid* pixels) |
| 2104 | { |
| 2105 | GL2Encoder* ctx = (GL2Encoder*)self; |
Lingfeng Yang | 6906660 | 2016-04-12 09:29:11 -0700 | [diff] [blame] | 2106 | GLClientState* state = ctx->m_state; |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 2107 | |
| 2108 | SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM); |
| 2109 | SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM); |
| 2110 | SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM); |
| 2111 | // If unpack buffer is nonzero, verify unmapped state. |
| 2112 | SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION); |
| 2113 | |
| 2114 | GLint max_texture_size; |
| 2115 | GLint max_cube_map_texture_size; |
| 2116 | ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size); |
| 2117 | ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size); |
| 2118 | SET_ERROR_IF(level < 0, GL_INVALID_VALUE); |
| 2119 | SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE); |
| 2120 | SET_ERROR_IF((target == GL_TEXTURE_CUBE_MAP) && |
| 2121 | (level > ilog2(max_cube_map_texture_size)), GL_INVALID_VALUE); |
| 2122 | SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE); |
| 2123 | SET_ERROR_IF(width > max_texture_size, GL_INVALID_VALUE); |
| 2124 | SET_ERROR_IF(height > max_texture_size, GL_INVALID_VALUE); |
| 2125 | SET_ERROR_IF(GLESv2Validation::isCubeMapTarget(target) && width > max_cube_map_texture_size, GL_INVALID_VALUE); |
| 2126 | SET_ERROR_IF(GLESv2Validation::isCubeMapTarget(target) && height > max_cube_map_texture_size, GL_INVALID_VALUE); |
| 2127 | SET_ERROR_IF(border != 0, GL_INVALID_VALUE); |
| 2128 | // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type. |
| 2129 | SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) && |
| 2130 | ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) && |
| 2131 | (ctx->m_state->pboNeededDataSize(width, height, 1, format, type, 0) > |
| 2132 | ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size), |
| 2133 | GL_INVALID_OPERATION); |
| 2134 | SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) && |
| 2135 | ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) && |
| 2136 | (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size % |
| 2137 | glSizeof(type)), |
| 2138 | GL_INVALID_OPERATION); |
| 2139 | SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) && |
| 2140 | ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) && |
| 2141 | ((uintptr_t)pixels % glSizeof(type)), |
| 2142 | GL_INVALID_OPERATION); |
| 2143 | SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION); |
| 2144 | |
| 2145 | GLenum stateTarget = target; |
| 2146 | if (target == GL_TEXTURE_CUBE_MAP_POSITIVE_X || |
| 2147 | target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y || |
| 2148 | target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z || |
| 2149 | target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X || |
| 2150 | target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y || |
| 2151 | target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) |
| 2152 | stateTarget = GL_TEXTURE_CUBE_MAP; |
| 2153 | |
| 2154 | state->setBoundTextureInternalFormat(stateTarget, internalformat); |
| 2155 | state->setBoundTextureFormat(stateTarget, format); |
| 2156 | state->setBoundTextureType(stateTarget, type); |
| 2157 | state->setBoundTextureDims(stateTarget, level, width, height, 1); |
| 2158 | |
bohu | 26a9298 | 2014-11-25 16:50:37 -0800 | [diff] [blame] | 2159 | if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { |
| 2160 | ctx->override2DTextureTarget(target); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 2161 | } |
Lingfeng Yang | 6906660 | 2016-04-12 09:29:11 -0700 | [diff] [blame] | 2162 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 2163 | if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) { |
| 2164 | ctx->glTexImage2DOffsetAEMU( |
| 2165 | ctx, target, level, internalformat, |
| 2166 | width, height, border, |
| 2167 | format, type, (uintptr_t)pixels); |
bohu | 26a9298 | 2014-11-25 16:50:37 -0800 | [diff] [blame] | 2168 | } else { |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 2169 | ctx->m_glTexImage2D_enc( |
| 2170 | ctx, target, level, internalformat, |
| 2171 | width, height, border, |
| 2172 | format, type, pixels); |
| 2173 | } |
| 2174 | |
| 2175 | if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { |
| 2176 | ctx->restore2DTextureTarget(target); |
bohu | 26a9298 | 2014-11-25 16:50:37 -0800 | [diff] [blame] | 2177 | } |
| 2178 | } |
| 2179 | |
Yahan Zhou | 2a20829 | 2016-06-22 15:36:04 -0700 | [diff] [blame] | 2180 | void GL2Encoder::s_glTexSubImage2D(void* self, GLenum target, GLint level, |
| 2181 | GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, |
| 2182 | GLenum type, const GLvoid* pixels) |
| 2183 | { |
| 2184 | GL2Encoder* ctx = (GL2Encoder*)self; |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 2185 | GLClientState* state = ctx->m_state; |
| 2186 | |
| 2187 | SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM); |
| 2188 | SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM); |
| 2189 | SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM); |
| 2190 | // If unpack buffer is nonzero, verify unmapped state. |
| 2191 | SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION); |
| 2192 | |
| 2193 | GLint max_texture_size; |
| 2194 | GLint max_cube_map_texture_size; |
| 2195 | ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size); |
| 2196 | ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size); |
| 2197 | SET_ERROR_IF(level < 0, GL_INVALID_VALUE); |
| 2198 | SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE); |
| 2199 | SET_ERROR_IF(GLESv2Validation::isCubeMapTarget(target) && |
| 2200 | level > ilog2(max_cube_map_texture_size), GL_INVALID_VALUE); |
| 2201 | SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE); |
| 2202 | SET_ERROR_IF(xoffset < 0 || yoffset < 0, GL_INVALID_VALUE); |
| 2203 | |
| 2204 | GLuint tex = state->getBoundTexture(target); |
| 2205 | GLsizei neededWidth = xoffset + width; |
| 2206 | GLsizei neededHeight = yoffset + height; |
| 2207 | GLsizei neededDepth = 1; |
| 2208 | |
| 2209 | if (tex && !state->queryTexEGLImageBacked(tex)) { |
| 2210 | SET_ERROR_IF( |
| 2211 | (neededWidth > state->queryTexWidth(level, tex) || |
| 2212 | neededHeight > state->queryTexHeight(level, tex) || |
| 2213 | neededDepth > state->queryTexDepth(level, tex)), |
| 2214 | GL_INVALID_VALUE); |
| 2215 | } |
| 2216 | |
| 2217 | // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type. |
| 2218 | SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) && |
| 2219 | ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) && |
| 2220 | (state->pboNeededDataSize(width, height, 1, format, type, 0) > |
| 2221 | ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size), |
| 2222 | GL_INVALID_OPERATION); |
| 2223 | SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) && |
| 2224 | ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) && |
| 2225 | (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size % |
| 2226 | glSizeof(type)), |
| 2227 | GL_INVALID_OPERATION); |
| 2228 | SET_ERROR_IF(!ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) && !pixels, GL_INVALID_OPERATION); |
Yahan Zhou | 2a20829 | 2016-06-22 15:36:04 -0700 | [diff] [blame] | 2229 | |
| 2230 | if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { |
| 2231 | ctx->override2DTextureTarget(target); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 2232 | } |
| 2233 | |
| 2234 | if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) { |
| 2235 | ctx->glTexSubImage2DOffsetAEMU( |
| 2236 | ctx, target, level, |
| 2237 | xoffset, yoffset, width, height, |
| 2238 | format, type, (uintptr_t)pixels); |
Yahan Zhou | 2a20829 | 2016-06-22 15:36:04 -0700 | [diff] [blame] | 2239 | } else { |
| 2240 | ctx->m_glTexSubImage2D_enc(ctx, target, level, xoffset, yoffset, width, |
| 2241 | height, format, type, pixels); |
| 2242 | } |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 2243 | |
| 2244 | if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { |
| 2245 | ctx->restore2DTextureTarget(target); |
| 2246 | } |
Yahan Zhou | 2a20829 | 2016-06-22 15:36:04 -0700 | [diff] [blame] | 2247 | } |
bohu | 26a9298 | 2014-11-25 16:50:37 -0800 | [diff] [blame] | 2248 | |
Lingfeng Yang | e00ec9d | 2016-09-16 08:54:03 -0700 | [diff] [blame] | 2249 | void GL2Encoder::s_glCopyTexImage2D(void* self, GLenum target, GLint level, |
| 2250 | GLenum internalformat, GLint x, GLint y, |
| 2251 | GLsizei width, GLsizei height, GLint border) |
| 2252 | { |
| 2253 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 2254 | GLClientState* state = ctx->m_state; |
| 2255 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 2256 | SET_ERROR_IF(ctx->glCheckFramebufferStatus(ctx, GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE, |
| 2257 | GL_INVALID_FRAMEBUFFER_OPERATION); |
Lingfeng Yang | e00ec9d | 2016-09-16 08:54:03 -0700 | [diff] [blame] | 2258 | // This is needed to work around underlying OpenGL drivers |
| 2259 | // (such as those feeding some some AMD GPUs) that expect |
| 2260 | // positive components of cube maps to be defined _before_ |
| 2261 | // the negative components (otherwise a segfault occurs). |
| 2262 | GLenum extraTarget = |
| 2263 | state->copyTexImageLuminanceCubeMapAMDWorkaround |
| 2264 | (target, level, internalformat); |
| 2265 | |
| 2266 | if (extraTarget) { |
| 2267 | ctx->m_glCopyTexImage2D_enc(ctx, extraTarget, level, internalformat, |
| 2268 | x, y, width, height, border); |
| 2269 | } |
| 2270 | |
| 2271 | ctx->m_glCopyTexImage2D_enc(ctx, target, level, internalformat, |
| 2272 | x, y, width, height, border); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 2273 | |
| 2274 | state->setBoundTextureInternalFormat(target, internalformat); |
| 2275 | state->setBoundTextureDims(target, level, width, height, 1); |
Lingfeng Yang | e00ec9d | 2016-09-16 08:54:03 -0700 | [diff] [blame] | 2276 | } |
| 2277 | |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 2278 | void GL2Encoder::s_glTexParameteriv(void* self, |
| 2279 | GLenum target, GLenum pname, const GLint* params) |
| 2280 | { |
| 2281 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 2282 | const GLClientState* state = ctx->m_state; |
| 2283 | |
| 2284 | SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES && |
| 2285 | !isValidTextureExternalParam(pname, (GLenum)params[0])), |
| 2286 | GL_INVALID_ENUM); |
| 2287 | |
| 2288 | if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { |
| 2289 | ctx->override2DTextureTarget(target); |
| 2290 | ctx->m_glTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params); |
Lingfeng Yang | b5c03d5 | 2016-09-07 14:40:03 -0700 | [diff] [blame] | 2291 | ctx->restore2DTextureTarget(target); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 2292 | } else { |
| 2293 | ctx->m_glTexParameteriv_enc(ctx, target, pname, params); |
| 2294 | } |
| 2295 | } |
| 2296 | |
Lingfeng Yang | b5c03d5 | 2016-09-07 14:40:03 -0700 | [diff] [blame] | 2297 | bool GL2Encoder::texture2DNeedsOverride(GLenum target) const { |
| 2298 | return (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) && |
| 2299 | target != m_state->getPriorityEnabledTarget(GL_TEXTURE_2D); |
| 2300 | } |
| 2301 | |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 2302 | void GL2Encoder::override2DTextureTarget(GLenum target) |
| 2303 | { |
Lingfeng Yang | b5c03d5 | 2016-09-07 14:40:03 -0700 | [diff] [blame] | 2304 | if (texture2DNeedsOverride(target)) { |
| 2305 | m_glBindTexture_enc(this, GL_TEXTURE_2D, |
| 2306 | m_state->getBoundTexture(target)); |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 2307 | } |
| 2308 | } |
| 2309 | |
Lingfeng Yang | b5c03d5 | 2016-09-07 14:40:03 -0700 | [diff] [blame] | 2310 | void GL2Encoder::restore2DTextureTarget(GLenum target) |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 2311 | { |
Lingfeng Yang | b5c03d5 | 2016-09-07 14:40:03 -0700 | [diff] [blame] | 2312 | if (texture2DNeedsOverride(target)) { |
Lingfeng Yang | 5bbf529 | 2017-04-24 18:52:56 -0700 | [diff] [blame] | 2313 | GLuint priorityEnabledBoundTexture = |
Lingfeng Yang | b5c03d5 | 2016-09-07 14:40:03 -0700 | [diff] [blame] | 2314 | m_state->getBoundTexture( |
Lingfeng Yang | 5bbf529 | 2017-04-24 18:52:56 -0700 | [diff] [blame] | 2315 | m_state->getPriorityEnabledTarget(GL_TEXTURE_2D)); |
| 2316 | GLuint texture2DBoundTexture = |
| 2317 | m_state->getBoundTexture(GL_TEXTURE_2D); |
| 2318 | if (!priorityEnabledBoundTexture) { |
| 2319 | m_glBindTexture_enc(this, GL_TEXTURE_2D, texture2DBoundTexture); |
| 2320 | } else { |
| 2321 | m_glBindTexture_enc(this, GL_TEXTURE_2D, priorityEnabledBoundTexture); |
| 2322 | } |
Lingfeng Yang | b5c03d5 | 2016-09-07 14:40:03 -0700 | [diff] [blame] | 2323 | } |
keunyoung | b85b275 | 2013-03-08 12:28:03 -0800 | [diff] [blame] | 2324 | } |
Lingfeng Yang | 57cb41b | 2016-04-08 14:42:34 -0700 | [diff] [blame] | 2325 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 2326 | void GL2Encoder::associateEGLImage(GLenum target, GLeglImageOES eglImage) { |
| 2327 | m_state->setBoundEGLImage(target, eglImage); |
| 2328 | } |
| 2329 | |
| 2330 | |
| 2331 | GLuint GL2Encoder::boundBuffer(GLenum target) const { |
| 2332 | return m_state->getBuffer(target); |
| 2333 | } |
| 2334 | |
| 2335 | BufferData* GL2Encoder::getBufferData(GLenum target) const { |
| 2336 | GLuint bufferId = m_state->getBuffer(target); |
| 2337 | if (!bufferId) return NULL; |
| 2338 | return m_shared->getBufferData(bufferId); |
| 2339 | } |
| 2340 | |
| 2341 | BufferData* GL2Encoder::getBufferDataById(GLuint bufferId) const { |
| 2342 | if (!bufferId) return NULL; |
| 2343 | return m_shared->getBufferData(bufferId); |
| 2344 | } |
| 2345 | |
| 2346 | bool GL2Encoder::isBufferMapped(GLuint buffer) const { |
| 2347 | return m_shared->getBufferData(buffer)->m_mapped; |
| 2348 | } |
| 2349 | |
| 2350 | bool GL2Encoder::isBufferTargetMapped(GLenum target) const { |
| 2351 | BufferData* buf = getBufferData(target); |
| 2352 | if (!buf) return false; |
| 2353 | return buf->m_mapped; |
| 2354 | } |
| 2355 | |
Lingfeng Yang | 57cb41b | 2016-04-08 14:42:34 -0700 | [diff] [blame] | 2356 | void GL2Encoder::s_glGenRenderbuffers(void* self, |
| 2357 | GLsizei n, GLuint* renderbuffers) { |
| 2358 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 2359 | GLClientState* state = ctx->m_state; |
| 2360 | |
| 2361 | SET_ERROR_IF(n < 0, GL_INVALID_VALUE); |
| 2362 | |
| 2363 | ctx->m_glGenFramebuffers_enc(self, n, renderbuffers); |
| 2364 | state->addRenderbuffers(n, renderbuffers); |
| 2365 | } |
| 2366 | |
| 2367 | void GL2Encoder::s_glDeleteRenderbuffers(void* self, |
| 2368 | GLsizei n, const GLuint* renderbuffers) { |
| 2369 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 2370 | GLClientState* state = ctx->m_state; |
| 2371 | |
| 2372 | SET_ERROR_IF(n < 0, GL_INVALID_VALUE); |
| 2373 | |
| 2374 | ctx->m_glDeleteRenderbuffers_enc(self, n, renderbuffers); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 2375 | |
| 2376 | // Nope, lets just leak those for now. |
| 2377 | // The spec has an *amazingly* convoluted set of conditions for when |
| 2378 | // render buffers are actually deleted: |
| 2379 | // glDeleteRenderbuffers deletes the n renderbuffer objects whose names are stored in the array addressed by renderbuffers. Unused names in renderbuffers that have been marked as used for the purposes of glGenRenderbuffers are marked as unused again. The name zero is reserved by the GL and is silently ignored, should it occur in renderbuffers, as are other unused names. Once a renderbuffer object is deleted, its name is again unused and it has no contents. If a renderbuffer that is currently bound to the target GL_RENDERBUFFER is deleted, it is as though glBindRenderbuffer had been executed with a target of GL_RENDERBUFFER and a name of zero. |
| 2380 | // |
| 2381 | // If a renderbuffer object is attached to one or more attachment points in the currently bound framebuffer, then it as if glFramebufferRenderbuffer had been called, with a renderbuffer of zero for each attachment point to which this image was attached in the currently bound framebuffer. In other words, this renderbuffer object is first detached from all attachment ponits in the currently bound framebuffer. ***Note that the renderbuffer image is specifically not detached from any non-bound framebuffers*** |
| 2382 | // |
| 2383 | // So, just detach this one from the bound FBO, and ignore the rest. |
| 2384 | for (int i = 0; i < n; i++) { |
| 2385 | state->detachRbo(renderbuffers[i]); |
| 2386 | } |
| 2387 | // state->removeRenderbuffers(n, renderbuffers); |
Lingfeng Yang | 57cb41b | 2016-04-08 14:42:34 -0700 | [diff] [blame] | 2388 | } |
| 2389 | |
| 2390 | void GL2Encoder::s_glBindRenderbuffer(void* self, |
| 2391 | GLenum target, GLuint renderbuffer) { |
| 2392 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 2393 | GLClientState* state = ctx->m_state; |
| 2394 | |
| 2395 | SET_ERROR_IF((target != GL_RENDERBUFFER), |
| 2396 | GL_INVALID_ENUM); |
| 2397 | |
| 2398 | ctx->m_glBindRenderbuffer_enc(self, target, renderbuffer); |
| 2399 | state->bindRenderbuffer(target, renderbuffer); |
| 2400 | } |
| 2401 | |
Lingfeng Yang | 6906660 | 2016-04-12 09:29:11 -0700 | [diff] [blame] | 2402 | void GL2Encoder::s_glRenderbufferStorage(void* self, |
| 2403 | GLenum target, GLenum internalformat, |
| 2404 | GLsizei width, GLsizei height) { |
| 2405 | GL2Encoder* ctx = (GL2Encoder*) self; |
| 2406 | GLClientState* state = ctx->m_state; |
| 2407 | |
| 2408 | SET_ERROR_IF(target != GL_RENDERBUFFER, GL_INVALID_ENUM); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 2409 | SET_ERROR_IF( |
| 2410 | !GLESv2Validation::rboFormat(ctx, internalformat), |
| 2411 | GL_INVALID_ENUM); |
Lingfeng Yang | 6906660 | 2016-04-12 09:29:11 -0700 | [diff] [blame] | 2412 | |
| 2413 | state->setBoundRenderbufferFormat(internalformat); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 2414 | state->setBoundRenderbufferSamples(0); |
| 2415 | |
Lingfeng Yang | 6906660 | 2016-04-12 09:29:11 -0700 | [diff] [blame] | 2416 | ctx->m_glRenderbufferStorage_enc(self, target, internalformat, |
| 2417 | width, height); |
| 2418 | } |
| 2419 | |
Lingfeng Yang | 57cb41b | 2016-04-08 14:42:34 -0700 | [diff] [blame] | 2420 | void GL2Encoder::s_glFramebufferRenderbuffer(void* self, |
| 2421 | GLenum target, GLenum attachment, |
| 2422 | GLenum renderbuffertarget, GLuint renderbuffer) { |
| 2423 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 2424 | GLClientState* state = ctx->m_state; |
| 2425 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 2426 | SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM); |
| 2427 | SET_ERROR_IF(!GLESv2Validation::framebufferAttachment(ctx, attachment), GL_INVALID_ENUM); |
| 2428 | state->attachRbo(target, attachment, renderbuffer); |
Lingfeng Yang | 57cb41b | 2016-04-08 14:42:34 -0700 | [diff] [blame] | 2429 | |
| 2430 | ctx->m_glFramebufferRenderbuffer_enc(self, target, attachment, renderbuffertarget, renderbuffer); |
| 2431 | } |
| 2432 | |
| 2433 | void GL2Encoder::s_glGenFramebuffers(void* self, |
| 2434 | GLsizei n, GLuint* framebuffers) { |
| 2435 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 2436 | GLClientState* state = ctx->m_state; |
| 2437 | |
| 2438 | SET_ERROR_IF(n < 0, GL_INVALID_VALUE); |
| 2439 | |
| 2440 | ctx->m_glGenFramebuffers_enc(self, n, framebuffers); |
| 2441 | state->addFramebuffers(n, framebuffers); |
| 2442 | } |
| 2443 | |
| 2444 | void GL2Encoder::s_glDeleteFramebuffers(void* self, |
| 2445 | GLsizei n, const GLuint* framebuffers) { |
| 2446 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 2447 | GLClientState* state = ctx->m_state; |
| 2448 | |
| 2449 | SET_ERROR_IF(n < 0, GL_INVALID_VALUE); |
| 2450 | |
| 2451 | ctx->m_glDeleteFramebuffers_enc(self, n, framebuffers); |
| 2452 | state->removeFramebuffers(n, framebuffers); |
| 2453 | } |
| 2454 | |
| 2455 | void GL2Encoder::s_glBindFramebuffer(void* self, |
| 2456 | GLenum target, GLuint framebuffer) { |
| 2457 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 2458 | GLClientState* state = ctx->m_state; |
| 2459 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 2460 | SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM); |
Lingfeng Yang | 57cb41b | 2016-04-08 14:42:34 -0700 | [diff] [blame] | 2461 | |
| 2462 | state->bindFramebuffer(target, framebuffer); |
| 2463 | |
| 2464 | ctx->m_glBindFramebuffer_enc(self, target, framebuffer); |
| 2465 | } |
| 2466 | |
| 2467 | void GL2Encoder::s_glFramebufferTexture2D(void* self, |
| 2468 | GLenum target, GLenum attachment, |
| 2469 | GLenum textarget, GLuint texture, GLint level) { |
| 2470 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 2471 | GLClientState* state = ctx->m_state; |
| 2472 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 2473 | SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM); |
| 2474 | SET_ERROR_IF(!GLESv2Validation::framebufferAttachment(ctx, attachment), GL_INVALID_ENUM); |
| 2475 | state->attachTextureObject(target, attachment, texture); |
Lingfeng Yang | 57cb41b | 2016-04-08 14:42:34 -0700 | [diff] [blame] | 2476 | |
| 2477 | ctx->m_glFramebufferTexture2D_enc(self, target, attachment, textarget, texture, level); |
| 2478 | } |
| 2479 | |
| 2480 | void GL2Encoder::s_glFramebufferTexture3DOES(void* self, |
| 2481 | GLenum target, GLenum attachment, |
| 2482 | GLenum textarget, GLuint texture, GLint level, GLint zoffset) { |
| 2483 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 2484 | GLClientState* state = ctx->m_state; |
| 2485 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 2486 | state->attachTextureObject(target, attachment, texture); |
Lingfeng Yang | 57cb41b | 2016-04-08 14:42:34 -0700 | [diff] [blame] | 2487 | |
| 2488 | ctx->m_glFramebufferTexture3DOES_enc(self, target, attachment, textarget, texture, level, zoffset); |
| 2489 | } |
| 2490 | |
| 2491 | void GL2Encoder::s_glGetFramebufferAttachmentParameteriv(void* self, |
| 2492 | GLenum target, GLenum attachment, GLenum pname, GLint* params) { |
| 2493 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 2494 | const GLClientState* state = ctx->m_state; |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 2495 | SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM); |
| 2496 | SET_ERROR_IF(pname != GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME && |
| 2497 | pname != GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE && |
| 2498 | !state->attachmentHasObject(target, attachment), |
Lingfeng Yang | 57cb41b | 2016-04-08 14:42:34 -0700 | [diff] [blame] | 2499 | GL_INVALID_OPERATION); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 2500 | SET_ERROR_IF((pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL || |
| 2501 | pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE || |
| 2502 | pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER) && |
| 2503 | (!state->attachmentHasObject(target, attachment) || |
| 2504 | state->getBoundFramebufferAttachmentType(target, attachment) != |
| 2505 | FBO_ATTACHMENT_TEXTURE), |
| 2506 | !state->attachmentHasObject(target, attachment) ? |
| 2507 | GL_INVALID_OPERATION : GL_INVALID_ENUM); |
| 2508 | SET_ERROR_IF(attachment == GL_DEPTH_STENCIL_ATTACHMENT && |
| 2509 | pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME && |
| 2510 | (state->objectOfAttachment(target, GL_DEPTH_ATTACHMENT) != |
| 2511 | state->objectOfAttachment(target, GL_STENCIL_ATTACHMENT)), |
| 2512 | GL_INVALID_OPERATION); |
| 2513 | SET_ERROR_IF(state->boundFramebuffer(target) && |
| 2514 | (attachment == GL_BACK || |
| 2515 | attachment == GL_FRONT), |
| 2516 | GL_INVALID_OPERATION); |
Lingfeng Yang | 57cb41b | 2016-04-08 14:42:34 -0700 | [diff] [blame] | 2517 | ctx->m_glGetFramebufferAttachmentParameteriv_enc(self, target, attachment, pname, params); |
| 2518 | } |
Lingfeng Yang | 6906660 | 2016-04-12 09:29:11 -0700 | [diff] [blame] | 2519 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 2520 | bool GL2Encoder::isCompleteFbo(GLenum target, const GLClientState* state, |
Lingfeng Yang | 6906660 | 2016-04-12 09:29:11 -0700 | [diff] [blame] | 2521 | GLenum attachment) const { |
| 2522 | FboFormatInfo fbo_format_info; |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 2523 | state->getBoundFramebufferFormat(target, attachment, &fbo_format_info); |
Lingfeng Yang | 6906660 | 2016-04-12 09:29:11 -0700 | [diff] [blame] | 2524 | |
| 2525 | bool res; |
| 2526 | switch (fbo_format_info.type) { |
| 2527 | case FBO_ATTACHMENT_RENDERBUFFER: |
| 2528 | switch (fbo_format_info.rb_format) { |
| 2529 | case GL_R16F: |
| 2530 | case GL_RG16F: |
Lingfeng Yang | 6906660 | 2016-04-12 09:29:11 -0700 | [diff] [blame] | 2531 | case GL_RGBA16F: |
Lingfeng Yang | 931817b | 2017-01-27 06:50:56 -0800 | [diff] [blame] | 2532 | case GL_R32F: |
| 2533 | case GL_RG32F: |
| 2534 | case GL_RGBA32F: |
| 2535 | case GL_R11F_G11F_B10F: |
Lingfeng Yang | c92685e | 2017-01-30 20:06:39 -0800 | [diff] [blame] | 2536 | res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_float"); |
Lingfeng Yang | 931817b | 2017-01-27 06:50:56 -0800 | [diff] [blame] | 2537 | break; |
| 2538 | case GL_RGB16F: |
Lingfeng Yang | c92685e | 2017-01-30 20:06:39 -0800 | [diff] [blame] | 2539 | res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_half_float"); |
Lingfeng Yang | 6906660 | 2016-04-12 09:29:11 -0700 | [diff] [blame] | 2540 | break; |
| 2541 | case GL_STENCIL_INDEX8: |
| 2542 | if (attachment == GL_STENCIL_ATTACHMENT) { |
| 2543 | res = true; |
| 2544 | } else { |
| 2545 | res = false; |
| 2546 | } |
| 2547 | break; |
| 2548 | default: |
| 2549 | res = true; |
| 2550 | } |
| 2551 | break; |
| 2552 | case FBO_ATTACHMENT_TEXTURE: |
Yahan Zhou | 68bfd8c | 2016-05-11 15:06:34 -0700 | [diff] [blame] | 2553 | switch (fbo_format_info.tex_internalformat) { |
Yahan Zhou | 68bfd8c | 2016-05-11 15:06:34 -0700 | [diff] [blame] | 2554 | case GL_R16F: |
| 2555 | case GL_RG16F: |
| 2556 | case GL_RGBA16F: |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 2557 | case GL_R32F: |
| 2558 | case GL_RG32F: |
| 2559 | case GL_RGBA32F: |
Lingfeng Yang | 931817b | 2017-01-27 06:50:56 -0800 | [diff] [blame] | 2560 | case GL_R11F_G11F_B10F: |
Lingfeng Yang | c92685e | 2017-01-30 20:06:39 -0800 | [diff] [blame] | 2561 | res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_float"); |
Lingfeng Yang | 931817b | 2017-01-27 06:50:56 -0800 | [diff] [blame] | 2562 | break; |
| 2563 | case GL_RGB16F: |
Lingfeng Yang | c92685e | 2017-01-30 20:06:39 -0800 | [diff] [blame] | 2564 | res = majorVersion() >= 3 && hasExtension("GL_EXT_color_buffer_half_float"); |
Lingfeng Yang | 931817b | 2017-01-27 06:50:56 -0800 | [diff] [blame] | 2565 | break; |
| 2566 | case GL_RED: |
| 2567 | case GL_RG: |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 2568 | case GL_SRGB8: |
| 2569 | case GL_RGB32UI: |
| 2570 | case GL_RGB16UI: |
| 2571 | case GL_RGB8UI: |
| 2572 | case GL_RGB32I: |
| 2573 | case GL_RGB16I: |
| 2574 | case GL_RGB8I: |
| 2575 | case GL_R8_SNORM: |
| 2576 | case GL_RG8_SNORM: |
| 2577 | case GL_RGB8_SNORM: |
| 2578 | case GL_RGBA8_SNORM: |
Yahan Zhou | 68bfd8c | 2016-05-11 15:06:34 -0700 | [diff] [blame] | 2579 | res = false; |
| 2580 | break; |
Lingfeng Yang | 6906660 | 2016-04-12 09:29:11 -0700 | [diff] [blame] | 2581 | // No float/half-float formats allowed for RGB(A) |
Yahan Zhou | 68bfd8c | 2016-05-11 15:06:34 -0700 | [diff] [blame] | 2582 | case GL_RGB: |
| 2583 | case GL_RGBA: |
Lingfeng Yang | 6906660 | 2016-04-12 09:29:11 -0700 | [diff] [blame] | 2584 | switch (fbo_format_info.tex_type) { |
| 2585 | case GL_FLOAT: |
| 2586 | case GL_HALF_FLOAT_OES: |
Yahan Zhou | 68bfd8c | 2016-05-11 15:06:34 -0700 | [diff] [blame] | 2587 | case GL_UNSIGNED_INT_10F_11F_11F_REV: |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 2588 | case GL_UNSIGNED_INT_2_10_10_10_REV: |
Lingfeng Yang | 6906660 | 2016-04-12 09:29:11 -0700 | [diff] [blame] | 2589 | res = false; |
| 2590 | break; |
| 2591 | default: |
| 2592 | res = true; |
| 2593 | } |
Yahan Zhou | 68bfd8c | 2016-05-11 15:06:34 -0700 | [diff] [blame] | 2594 | break; |
| 2595 | default: |
Lingfeng Yang | 6906660 | 2016-04-12 09:29:11 -0700 | [diff] [blame] | 2596 | res = true; |
| 2597 | } |
| 2598 | break; |
| 2599 | case FBO_ATTACHMENT_NONE: |
| 2600 | res = true; |
| 2601 | break; |
| 2602 | default: |
| 2603 | res = true; |
| 2604 | } |
| 2605 | return res; |
| 2606 | } |
| 2607 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 2608 | bool GL2Encoder::checkFramebufferCompleteness(GLenum target, const GLClientState* state) const { |
| 2609 | bool res = true; |
| 2610 | |
| 2611 | for (int i = 0; i < state->getMaxColorAttachments(); i++) { |
| 2612 | res = res && isCompleteFbo(target, state, glUtilsColorAttachmentName(i)); |
| 2613 | } |
| 2614 | |
| 2615 | res = res && isCompleteFbo(target, state, GL_DEPTH_ATTACHMENT); |
| 2616 | res = res && isCompleteFbo(target, state, GL_STENCIL_ATTACHMENT); |
| 2617 | |
| 2618 | return res; |
| 2619 | } |
| 2620 | |
Lingfeng Yang | 6906660 | 2016-04-12 09:29:11 -0700 | [diff] [blame] | 2621 | GLenum GL2Encoder::s_glCheckFramebufferStatus(void* self, GLenum target) { |
| 2622 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 2623 | GLClientState* state = ctx->m_state; |
| 2624 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 2625 | bool fboCompleteByCodec = |
| 2626 | ctx->checkFramebufferCompleteness(target, state); |
| 2627 | |
| 2628 | if (!fboCompleteByCodec) { |
| 2629 | state->setCheckFramebufferStatus(target, GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT); |
Lingfeng Yang | 6906660 | 2016-04-12 09:29:11 -0700 | [diff] [blame] | 2630 | return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; |
| 2631 | } else { |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 2632 | // double check with underlying opengl to avoid craziness. |
Lingfeng Yang | 6906660 | 2016-04-12 09:29:11 -0700 | [diff] [blame] | 2633 | GLenum host_checkstatus = ctx->m_glCheckFramebufferStatus_enc(self, target); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 2634 | state->setCheckFramebufferStatus(target, host_checkstatus); |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 2635 | if (host_checkstatus == GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS) return GL_FRAMEBUFFER_COMPLETE; |
Lingfeng Yang | 6906660 | 2016-04-12 09:29:11 -0700 | [diff] [blame] | 2636 | return host_checkstatus; |
| 2637 | } |
| 2638 | } |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 2639 | |
| 2640 | void GL2Encoder::s_glGenVertexArrays(void* self, GLsizei n, GLuint* arrays) { |
| 2641 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 2642 | GLClientState* state = ctx->m_state; |
| 2643 | SET_ERROR_IF(n < 0, GL_INVALID_VALUE); |
| 2644 | |
| 2645 | ctx->m_glGenVertexArrays_enc(self, n, arrays); |
| 2646 | for (int i = 0; i < n; i++) { |
| 2647 | ALOGV("%s: gen vao %u", __FUNCTION__, arrays[i]); |
| 2648 | } |
| 2649 | state->addVertexArrayObjects(n, arrays); |
| 2650 | } |
| 2651 | |
| 2652 | void GL2Encoder::s_glDeleteVertexArrays(void* self, GLsizei n, const GLuint* arrays) { |
| 2653 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 2654 | GLClientState* state = ctx->m_state; |
| 2655 | SET_ERROR_IF(n < 0, GL_INVALID_VALUE); |
| 2656 | |
| 2657 | ctx->m_glDeleteVertexArrays_enc(self, n, arrays); |
| 2658 | for (int i = 0; i < n; i++) { |
| 2659 | ALOGV("%s: delete vao %u", __FUNCTION__, arrays[i]); |
| 2660 | } |
| 2661 | state->removeVertexArrayObjects(n, arrays); |
| 2662 | } |
| 2663 | |
| 2664 | void GL2Encoder::s_glBindVertexArray(void* self, GLuint array) { |
| 2665 | ALOGV("%s: call. array=%u\n", __FUNCTION__, array); |
| 2666 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 2667 | GLClientState* state = ctx->m_state; |
| 2668 | SET_ERROR_IF(!state->isVertexArrayObject(array), GL_INVALID_OPERATION); |
| 2669 | ctx->m_glBindVertexArray_enc(self, array); |
| 2670 | state->setVertexArrayObject(array); |
| 2671 | } |
| 2672 | |
Lingfeng Yang | fb3d2bb | 2017-09-07 15:02:04 -0700 | [diff] [blame] | 2673 | void* GL2Encoder::s_glMapBufferOES(void* self, GLenum target, GLenum access) { |
| 2674 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 2675 | |
| 2676 | RET_AND_SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM, NULL); |
| 2677 | |
| 2678 | GLuint boundBuffer = ctx->m_state->getBuffer(target); |
| 2679 | |
| 2680 | RET_AND_SET_ERROR_IF(boundBuffer == 0, GL_INVALID_OPERATION, NULL); |
| 2681 | |
| 2682 | BufferData* buf = ctx->m_shared->getBufferData(boundBuffer); |
| 2683 | RET_AND_SET_ERROR_IF(!buf, GL_INVALID_VALUE, NULL); |
| 2684 | |
| 2685 | return ctx->glMapBufferRange(ctx, target, 0, buf->m_size, access); |
| 2686 | } |
| 2687 | |
| 2688 | GLboolean GL2Encoder::s_glUnmapBufferOES(void* self, GLenum target) { |
| 2689 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 2690 | |
| 2691 | return ctx->glUnmapBuffer(ctx, target); |
| 2692 | } |
| 2693 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 2694 | void* GL2Encoder::s_glMapBufferRange(void* self, GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) { |
| 2695 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 2696 | GLClientState* state = ctx->m_state; |
| 2697 | |
| 2698 | // begin validation (lots) |
| 2699 | |
| 2700 | RET_AND_SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM, NULL); |
| 2701 | |
| 2702 | GLuint boundBuffer = ctx->m_state->getBuffer(target); |
| 2703 | |
| 2704 | RET_AND_SET_ERROR_IF(boundBuffer == 0, GL_INVALID_OPERATION, NULL); |
| 2705 | |
| 2706 | BufferData* buf = ctx->m_shared->getBufferData(boundBuffer); |
| 2707 | RET_AND_SET_ERROR_IF(!buf, GL_INVALID_VALUE, NULL); |
| 2708 | |
| 2709 | GLsizeiptr bufferDataSize = buf->m_size; |
| 2710 | |
| 2711 | RET_AND_SET_ERROR_IF(offset < 0, GL_INVALID_VALUE, NULL); |
| 2712 | RET_AND_SET_ERROR_IF(length < 0, GL_INVALID_VALUE, NULL); |
| 2713 | RET_AND_SET_ERROR_IF(offset + length > bufferDataSize, GL_INVALID_VALUE, NULL); |
| 2714 | RET_AND_SET_ERROR_IF(access & ~GLESv2Validation::allBufferMapAccessFlags, GL_INVALID_VALUE, NULL); |
| 2715 | |
| 2716 | RET_AND_SET_ERROR_IF(buf->m_mapped, GL_INVALID_OPERATION, NULL); |
| 2717 | RET_AND_SET_ERROR_IF(!(access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)), GL_INVALID_OPERATION, NULL); |
| 2718 | RET_AND_SET_ERROR_IF( |
| 2719 | (access & GL_MAP_READ_BIT) && |
| 2720 | ((access & GL_MAP_INVALIDATE_RANGE_BIT) || |
| 2721 | (access & GL_MAP_INVALIDATE_BUFFER_BIT) || |
| 2722 | (access & GL_MAP_UNSYNCHRONIZED_BIT) || |
| 2723 | (access & GL_MAP_FLUSH_EXPLICIT_BIT)), GL_INVALID_OPERATION, NULL); |
| 2724 | |
| 2725 | // end validation; actually do stuff now |
| 2726 | |
| 2727 | buf->m_mapped = true; |
| 2728 | buf->m_mappedAccess = access; |
| 2729 | buf->m_mappedOffset = offset; |
| 2730 | buf->m_mappedLength = length; |
| 2731 | |
| 2732 | char* todo = (char*)buf->m_fixedBuffer.ptr() + offset; |
| 2733 | ctx->glMapBufferRangeAEMU( |
| 2734 | ctx, target, |
| 2735 | offset, length, |
| 2736 | access, |
| 2737 | todo); |
| 2738 | |
| 2739 | return todo; |
| 2740 | } |
| 2741 | |
| 2742 | GLboolean GL2Encoder::s_glUnmapBuffer(void* self, GLenum target) { |
| 2743 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 2744 | GLClientState* state = ctx->m_state; |
| 2745 | |
| 2746 | RET_AND_SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM, GL_FALSE); |
| 2747 | |
| 2748 | GLuint boundBuffer = ctx->m_state->getBuffer(target); |
| 2749 | |
| 2750 | RET_AND_SET_ERROR_IF(boundBuffer == 0, GL_INVALID_OPERATION, GL_FALSE); |
| 2751 | |
| 2752 | BufferData* buf = ctx->m_shared->getBufferData(boundBuffer); |
| 2753 | RET_AND_SET_ERROR_IF(!buf, GL_INVALID_VALUE, GL_FALSE); |
| 2754 | RET_AND_SET_ERROR_IF(!buf->m_mapped, GL_INVALID_OPERATION, GL_FALSE); |
| 2755 | |
Lingfeng Yang | 423129e | 2017-01-18 09:23:12 -0800 | [diff] [blame] | 2756 | if (buf->m_mappedAccess & GL_MAP_WRITE_BIT) { |
| 2757 | // invalide index range cache here |
| 2758 | if (buf->m_mappedAccess & GL_MAP_INVALIDATE_BUFFER_BIT) { |
| 2759 | buf->m_indexRangeCache.invalidateRange(0, buf->m_size); |
| 2760 | } else { |
| 2761 | buf->m_indexRangeCache.invalidateRange(buf->m_mappedOffset, buf->m_mappedLength); |
| 2762 | } |
| 2763 | } |
| 2764 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 2765 | GLboolean host_res = GL_TRUE; |
| 2766 | |
| 2767 | ctx->glUnmapBufferAEMU( |
| 2768 | ctx, target, |
| 2769 | buf->m_mappedOffset, |
| 2770 | buf->m_mappedLength, |
| 2771 | buf->m_mappedAccess, |
| 2772 | (void*)((char*)buf->m_fixedBuffer.ptr() + buf->m_mappedOffset), |
| 2773 | &host_res); |
| 2774 | |
| 2775 | buf->m_mapped = false; |
| 2776 | buf->m_mappedAccess = 0; |
| 2777 | buf->m_mappedOffset = 0; |
| 2778 | buf->m_mappedLength = 0; |
| 2779 | |
| 2780 | return host_res; |
| 2781 | } |
| 2782 | |
| 2783 | void GL2Encoder::s_glFlushMappedBufferRange(void* self, GLenum target, GLintptr offset, GLsizeiptr length) { |
| 2784 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 2785 | GLClientState* state = ctx->m_state; |
| 2786 | |
| 2787 | SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM); |
| 2788 | |
| 2789 | GLuint boundBuffer = ctx->m_state->getBuffer(target); |
| 2790 | SET_ERROR_IF(!boundBuffer, GL_INVALID_OPERATION); |
| 2791 | |
| 2792 | BufferData* buf = ctx->m_shared->getBufferData(boundBuffer); |
| 2793 | SET_ERROR_IF(!buf, GL_INVALID_VALUE); |
| 2794 | SET_ERROR_IF(!buf->m_mapped, GL_INVALID_OPERATION); |
| 2795 | SET_ERROR_IF(!(buf->m_mappedAccess & GL_MAP_FLUSH_EXPLICIT_BIT), GL_INVALID_OPERATION); |
| 2796 | |
| 2797 | SET_ERROR_IF(offset < 0, GL_INVALID_VALUE); |
| 2798 | SET_ERROR_IF(length < 0, GL_INVALID_VALUE); |
| 2799 | SET_ERROR_IF(offset + length > buf->m_mappedLength, GL_INVALID_VALUE); |
| 2800 | |
| 2801 | GLintptr totalOffset = buf->m_mappedOffset + offset; |
Lingfeng Yang | 423129e | 2017-01-18 09:23:12 -0800 | [diff] [blame] | 2802 | |
| 2803 | buf->m_indexRangeCache.invalidateRange(totalOffset, length); |
| 2804 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 2805 | ctx->glFlushMappedBufferRangeAEMU( |
| 2806 | ctx, target, |
| 2807 | totalOffset, |
| 2808 | length, |
| 2809 | buf->m_mappedAccess, |
| 2810 | (void*)((char*)buf->m_fixedBuffer.ptr() + totalOffset)); |
| 2811 | } |
| 2812 | |
| 2813 | void GL2Encoder::s_glCompressedTexImage2D(void* self, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data) { |
| 2814 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 2815 | GLClientState* state = ctx->m_state; |
| 2816 | |
| 2817 | SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM); |
| 2818 | // Filter compressed formats support. |
| 2819 | SET_ERROR_IF(!GLESv2Validation::supportedCompressedFormat(ctx, internalformat), GL_INVALID_ENUM); |
| 2820 | // Verify level <= log2(GL_MAX_TEXTURE_SIZE). |
| 2821 | GLint max_texture_size; |
| 2822 | GLint max_cube_map_texture_size; |
| 2823 | ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size); |
| 2824 | ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size); |
| 2825 | SET_ERROR_IF(level < 0, GL_INVALID_VALUE); |
| 2826 | SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE); |
| 2827 | SET_ERROR_IF(level > ilog2(max_cube_map_texture_size), GL_INVALID_VALUE); |
| 2828 | SET_ERROR_IF(width > max_texture_size, GL_INVALID_VALUE); |
| 2829 | SET_ERROR_IF(height > max_texture_size, GL_INVALID_VALUE); |
| 2830 | SET_ERROR_IF(border, GL_INVALID_VALUE); |
| 2831 | // If unpack buffer is nonzero, verify unmapped state. |
| 2832 | SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION); |
| 2833 | SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE); |
| 2834 | // If unpack buffer is nonzero, verify buffer data fits. |
| 2835 | SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) && |
| 2836 | ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) && |
| 2837 | (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size), |
| 2838 | GL_INVALID_OPERATION); |
| 2839 | // TODO: Fix: |
| 2840 | // If |imageSize| is inconsistent with compressed dimensions. |
| 2841 | // SET_ERROR_IF(GLESv2Validation::compressedTexImageSize(internalformat, width, height, 1) != imageSize, GL_INVALID_VALUE); |
| 2842 | |
| 2843 | GLenum stateTarget = target; |
| 2844 | if (target == GL_TEXTURE_CUBE_MAP_POSITIVE_X || |
| 2845 | target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y || |
| 2846 | target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z || |
| 2847 | target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X || |
| 2848 | target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y || |
| 2849 | target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) |
| 2850 | stateTarget = GL_TEXTURE_CUBE_MAP; |
| 2851 | state->setBoundTextureInternalFormat(stateTarget, (GLint)internalformat); |
| 2852 | state->setBoundTextureDims(stateTarget, level, width, height, 1); |
| 2853 | |
Lingfeng Yang | a9fff6a | 2018-03-02 13:42:51 -0800 | [diff] [blame] | 2854 | if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { |
| 2855 | ctx->override2DTextureTarget(target); |
| 2856 | } |
| 2857 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 2858 | if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) { |
| 2859 | ctx->glCompressedTexImage2DOffsetAEMU( |
| 2860 | ctx, target, level, internalformat, |
| 2861 | width, height, border, |
| 2862 | imageSize, (uintptr_t)data); |
| 2863 | } else { |
| 2864 | ctx->m_glCompressedTexImage2D_enc( |
| 2865 | ctx, target, level, internalformat, |
| 2866 | width, height, border, |
| 2867 | imageSize, data); |
| 2868 | } |
Lingfeng Yang | a9fff6a | 2018-03-02 13:42:51 -0800 | [diff] [blame] | 2869 | |
| 2870 | if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { |
| 2871 | ctx->restore2DTextureTarget(target); |
| 2872 | } |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 2873 | } |
| 2874 | |
| 2875 | void GL2Encoder::s_glCompressedTexSubImage2D(void* self, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data) { |
| 2876 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 2877 | GLClientState* state = ctx->m_state; |
| 2878 | |
| 2879 | SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM); |
| 2880 | // If unpack buffer is nonzero, verify unmapped state. |
| 2881 | SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION); |
| 2882 | GLint max_texture_size; |
| 2883 | GLint max_cube_map_texture_size; |
| 2884 | ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size); |
| 2885 | ctx->glGetIntegerv(ctx, GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size); |
| 2886 | SET_ERROR_IF(level < 0, GL_INVALID_VALUE); |
| 2887 | SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE); |
| 2888 | SET_ERROR_IF(level > ilog2(max_cube_map_texture_size), GL_INVALID_VALUE); |
| 2889 | SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE); |
| 2890 | // If unpack buffer is nonzero, verify buffer data fits. |
| 2891 | SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) && |
| 2892 | ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) && |
| 2893 | (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size), |
| 2894 | GL_INVALID_OPERATION); |
| 2895 | SET_ERROR_IF(xoffset < 0 || yoffset < 0, GL_INVALID_VALUE); |
| 2896 | |
Lingfeng Yang | a9fff6a | 2018-03-02 13:42:51 -0800 | [diff] [blame] | 2897 | if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { |
| 2898 | ctx->override2DTextureTarget(target); |
| 2899 | } |
| 2900 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 2901 | if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) { |
| 2902 | ctx->glCompressedTexSubImage2DOffsetAEMU( |
| 2903 | ctx, target, level, |
| 2904 | xoffset, yoffset, |
| 2905 | width, height, format, |
| 2906 | imageSize, (uintptr_t)data); |
| 2907 | } else { |
| 2908 | ctx->m_glCompressedTexSubImage2D_enc( |
| 2909 | ctx, target, level, |
| 2910 | xoffset, yoffset, |
| 2911 | width, height, format, |
| 2912 | imageSize, data); |
| 2913 | } |
Lingfeng Yang | a9fff6a | 2018-03-02 13:42:51 -0800 | [diff] [blame] | 2914 | |
| 2915 | if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { |
| 2916 | ctx->restore2DTextureTarget(target); |
| 2917 | } |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 2918 | } |
| 2919 | |
| 2920 | void GL2Encoder::s_glBindBufferRange(void* self, GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) { |
| 2921 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 2922 | GLClientState* state = ctx->m_state; |
| 2923 | |
| 2924 | SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM); |
| 2925 | |
| 2926 | // Only works with certain targets |
| 2927 | SET_ERROR_IF( |
| 2928 | !(target == GL_ATOMIC_COUNTER_BUFFER || |
| 2929 | target == GL_SHADER_STORAGE_BUFFER || |
| 2930 | target == GL_TRANSFORM_FEEDBACK_BUFFER || |
| 2931 | target == GL_UNIFORM_BUFFER), |
| 2932 | GL_INVALID_ENUM); |
| 2933 | |
| 2934 | // Can't exceed range |
| 2935 | SET_ERROR_IF(index < 0 || |
| 2936 | index >= state->getMaxIndexedBufferBindings(target), |
| 2937 | GL_INVALID_VALUE); |
| 2938 | SET_ERROR_IF(buffer && size <= 0, GL_INVALID_VALUE); |
| 2939 | SET_ERROR_IF((target == GL_ATOMIC_COUNTER_BUFFER || |
| 2940 | target == GL_TRANSFORM_FEEDBACK_BUFFER) && |
| 2941 | (size % 4 || offset % 4), |
| 2942 | GL_INVALID_VALUE); |
| 2943 | |
| 2944 | GLint ssbo_offset_align, ubo_offset_align; |
| 2945 | ctx->s_glGetIntegerv(ctx, GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &ssbo_offset_align); |
| 2946 | ctx->s_glGetIntegerv(ctx, GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &ubo_offset_align); |
| 2947 | SET_ERROR_IF(target == GL_SHADER_STORAGE_BUFFER && |
| 2948 | offset % ssbo_offset_align, |
| 2949 | GL_INVALID_VALUE); |
| 2950 | SET_ERROR_IF(target == GL_UNIFORM_BUFFER && |
| 2951 | offset % ubo_offset_align, |
| 2952 | GL_INVALID_VALUE); |
| 2953 | |
| 2954 | state->bindBuffer(target, buffer); |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 2955 | ctx->m_state->addBuffer(buffer); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 2956 | state->bindIndexedBuffer(target, index, buffer, offset, size, 0, 0); |
| 2957 | ctx->m_glBindBufferRange_enc(self, target, index, buffer, offset, size); |
| 2958 | } |
| 2959 | |
| 2960 | void GL2Encoder::s_glBindBufferBase(void* self, GLenum target, GLuint index, GLuint buffer) { |
| 2961 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 2962 | GLClientState* state = ctx->m_state; |
| 2963 | |
| 2964 | SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM); |
| 2965 | |
| 2966 | // Only works with certain targets |
| 2967 | SET_ERROR_IF( |
| 2968 | !(target == GL_ATOMIC_COUNTER_BUFFER || |
| 2969 | target == GL_SHADER_STORAGE_BUFFER || |
| 2970 | target == GL_TRANSFORM_FEEDBACK_BUFFER || |
| 2971 | target == GL_UNIFORM_BUFFER), |
| 2972 | GL_INVALID_ENUM); |
| 2973 | // Can't exceed range |
| 2974 | SET_ERROR_IF(index < 0 || |
| 2975 | index >= state->getMaxIndexedBufferBindings(target), |
| 2976 | GL_INVALID_VALUE); |
| 2977 | |
| 2978 | state->bindBuffer(target, buffer); |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 2979 | ctx->m_state->addBuffer(buffer); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 2980 | BufferData* buf = ctx->getBufferDataById(buffer); |
| 2981 | state->bindIndexedBuffer(target, index, buffer, 0, buf ? buf->m_size : 0, 0, 0); |
| 2982 | ctx->m_glBindBufferBase_enc(self, target, index, buffer); |
| 2983 | } |
| 2984 | |
| 2985 | void GL2Encoder::s_glCopyBufferSubData(void *self , GLenum readtarget, GLenum writetarget, GLintptr readoffset, GLintptr writeoffset, GLsizeiptr size) { |
| 2986 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 2987 | GLClientState* state = ctx->m_state; |
| 2988 | |
| 2989 | SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, readtarget), GL_INVALID_ENUM); |
| 2990 | SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, writetarget), GL_INVALID_ENUM); |
| 2991 | SET_ERROR_IF((readtarget == GL_ATOMIC_COUNTER_BUFFER || |
| 2992 | readtarget == GL_DISPATCH_INDIRECT_BUFFER || |
| 2993 | readtarget == GL_DRAW_INDIRECT_BUFFER || |
| 2994 | readtarget == GL_SHADER_STORAGE_BUFFER), GL_INVALID_ENUM); |
| 2995 | SET_ERROR_IF((writetarget == GL_ATOMIC_COUNTER_BUFFER || |
| 2996 | writetarget == GL_DISPATCH_INDIRECT_BUFFER || |
| 2997 | writetarget == GL_DRAW_INDIRECT_BUFFER || |
| 2998 | writetarget == GL_SHADER_STORAGE_BUFFER), GL_INVALID_ENUM); |
| 2999 | SET_ERROR_IF(!ctx->boundBuffer(readtarget), GL_INVALID_OPERATION); |
| 3000 | SET_ERROR_IF(!ctx->boundBuffer(writetarget), GL_INVALID_OPERATION); |
| 3001 | SET_ERROR_IF(ctx->isBufferTargetMapped(readtarget), GL_INVALID_OPERATION); |
| 3002 | SET_ERROR_IF(ctx->isBufferTargetMapped(writetarget), GL_INVALID_OPERATION); |
| 3003 | SET_ERROR_IF(readoffset < 0, GL_INVALID_VALUE); |
| 3004 | SET_ERROR_IF(writeoffset < 0, GL_INVALID_VALUE); |
| 3005 | SET_ERROR_IF(size < 0, GL_INVALID_VALUE); |
| 3006 | SET_ERROR_IF( |
| 3007 | ctx->getBufferData(readtarget) && |
| 3008 | (readoffset + size > ctx->getBufferData(readtarget)->m_size), |
| 3009 | GL_INVALID_VALUE); |
| 3010 | SET_ERROR_IF( |
| 3011 | ctx->getBufferData(writetarget) && |
| 3012 | (writeoffset + size > ctx->getBufferData(writetarget)->m_size), |
| 3013 | GL_INVALID_VALUE); |
| 3014 | SET_ERROR_IF(readtarget == writetarget && |
| 3015 | !((writeoffset >= readoffset + size) || |
| 3016 | (readoffset >= writeoffset + size)), |
| 3017 | GL_INVALID_VALUE); |
| 3018 | |
| 3019 | ctx->m_glCopyBufferSubData_enc(self, readtarget, writetarget, readoffset, writeoffset, size); |
| 3020 | } |
| 3021 | |
| 3022 | void GL2Encoder::s_glGetBufferParameteriv(void* self, GLenum target, GLenum pname, GLint* params) { |
| 3023 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 3024 | |
| 3025 | SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM); |
| 3026 | SET_ERROR_IF( |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 3027 | target != GL_ARRAY_BUFFER && |
| 3028 | target != GL_ELEMENT_ARRAY_BUFFER && |
| 3029 | target != GL_COPY_READ_BUFFER && |
| 3030 | target != GL_COPY_WRITE_BUFFER && |
| 3031 | target != GL_PIXEL_PACK_BUFFER && |
| 3032 | target != GL_PIXEL_UNPACK_BUFFER && |
| 3033 | target != GL_TRANSFORM_FEEDBACK_BUFFER && |
| 3034 | target != GL_UNIFORM_BUFFER, |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 3035 | GL_INVALID_ENUM); |
| 3036 | SET_ERROR_IF(!GLESv2Validation::bufferParam(ctx, pname), GL_INVALID_ENUM); |
| 3037 | SET_ERROR_IF(!ctx->boundBuffer(target), GL_INVALID_OPERATION); |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 3038 | SET_ERROR_IF(pname != GL_BUFFER_ACCESS_FLAGS && |
| 3039 | pname != GL_BUFFER_MAPPED && |
| 3040 | pname != GL_BUFFER_SIZE && |
| 3041 | pname != GL_BUFFER_USAGE && |
| 3042 | pname != GL_BUFFER_MAP_LENGTH && |
| 3043 | pname != GL_BUFFER_MAP_OFFSET, |
| 3044 | GL_INVALID_ENUM); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 3045 | |
| 3046 | if (!params) return; |
| 3047 | |
| 3048 | BufferData* buf = ctx->getBufferData(target); |
| 3049 | |
| 3050 | switch (pname) { |
| 3051 | case GL_BUFFER_ACCESS_FLAGS: |
| 3052 | *params = buf ? buf->m_mappedAccess : 0; |
| 3053 | break; |
| 3054 | case GL_BUFFER_MAPPED: |
| 3055 | *params = buf ? (buf->m_mapped ? GL_TRUE : GL_FALSE) : GL_FALSE; |
| 3056 | break; |
| 3057 | case GL_BUFFER_SIZE: |
| 3058 | *params = buf ? buf->m_size : 0; |
| 3059 | break; |
| 3060 | case GL_BUFFER_USAGE: |
| 3061 | *params = buf ? buf->m_usage : GL_STATIC_DRAW; |
| 3062 | break; |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 3063 | case GL_BUFFER_MAP_LENGTH: |
| 3064 | *params = buf ? buf->m_mappedLength : 0; |
| 3065 | break; |
| 3066 | case GL_BUFFER_MAP_OFFSET: |
| 3067 | *params = buf ? buf->m_mappedOffset : 0; |
| 3068 | break; |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 3069 | default: |
| 3070 | break; |
| 3071 | } |
| 3072 | } |
| 3073 | |
| 3074 | void GL2Encoder::s_glGetBufferParameteri64v(void* self, GLenum target, GLenum pname, GLint64* params) { |
| 3075 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 3076 | |
| 3077 | SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM); |
| 3078 | SET_ERROR_IF( |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 3079 | target != GL_ARRAY_BUFFER && |
| 3080 | target != GL_ELEMENT_ARRAY_BUFFER && |
| 3081 | target != GL_COPY_READ_BUFFER && |
| 3082 | target != GL_COPY_WRITE_BUFFER && |
| 3083 | target != GL_PIXEL_PACK_BUFFER && |
| 3084 | target != GL_PIXEL_UNPACK_BUFFER && |
| 3085 | target != GL_TRANSFORM_FEEDBACK_BUFFER && |
| 3086 | target != GL_UNIFORM_BUFFER, |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 3087 | GL_INVALID_ENUM); |
| 3088 | SET_ERROR_IF(!GLESv2Validation::bufferParam(ctx, pname), GL_INVALID_ENUM); |
| 3089 | SET_ERROR_IF(!ctx->boundBuffer(target), GL_INVALID_OPERATION); |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 3090 | SET_ERROR_IF(pname != GL_BUFFER_ACCESS_FLAGS && |
| 3091 | pname != GL_BUFFER_MAPPED && |
| 3092 | pname != GL_BUFFER_SIZE && |
| 3093 | pname != GL_BUFFER_USAGE && |
| 3094 | pname != GL_BUFFER_MAP_LENGTH && |
| 3095 | pname != GL_BUFFER_MAP_OFFSET, |
| 3096 | GL_INVALID_ENUM); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 3097 | |
| 3098 | if (!params) return; |
| 3099 | |
| 3100 | BufferData* buf = ctx->getBufferData(target); |
| 3101 | |
| 3102 | switch (pname) { |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 3103 | case GL_BUFFER_ACCESS_FLAGS: |
| 3104 | *params = buf ? buf->m_mappedAccess : 0; |
| 3105 | break; |
| 3106 | case GL_BUFFER_MAPPED: |
| 3107 | *params = buf ? (buf->m_mapped ? GL_TRUE : GL_FALSE) : GL_FALSE; |
| 3108 | break; |
| 3109 | case GL_BUFFER_SIZE: |
| 3110 | *params = buf ? buf->m_size : 0; |
| 3111 | break; |
| 3112 | case GL_BUFFER_USAGE: |
| 3113 | *params = buf ? buf->m_usage : GL_STATIC_DRAW; |
| 3114 | break; |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 3115 | case GL_BUFFER_MAP_LENGTH: |
| 3116 | *params = buf ? buf->m_mappedLength : 0; |
| 3117 | break; |
| 3118 | case GL_BUFFER_MAP_OFFSET: |
| 3119 | *params = buf ? buf->m_mappedOffset : 0; |
| 3120 | break; |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 3121 | default: |
| 3122 | break; |
| 3123 | } |
| 3124 | } |
| 3125 | |
| 3126 | void GL2Encoder::s_glGetBufferPointerv(void* self, GLenum target, GLenum pname, GLvoid** params) { |
| 3127 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 3128 | SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM); |
| 3129 | SET_ERROR_IF( |
| 3130 | target == GL_ATOMIC_COUNTER_BUFFER || |
| 3131 | target == GL_DISPATCH_INDIRECT_BUFFER || |
| 3132 | target == GL_DRAW_INDIRECT_BUFFER || |
| 3133 | target == GL_SHADER_STORAGE_BUFFER, |
| 3134 | GL_INVALID_ENUM); |
| 3135 | SET_ERROR_IF(pname != GL_BUFFER_MAP_POINTER, GL_INVALID_ENUM); |
| 3136 | SET_ERROR_IF(!ctx->boundBuffer(target), GL_INVALID_OPERATION); |
| 3137 | if (!params) return; |
| 3138 | |
| 3139 | BufferData* buf = ctx->getBufferData(target); |
| 3140 | |
| 3141 | if (!buf || !buf->m_mapped) { *params = NULL; return; } |
| 3142 | |
| 3143 | *params = (GLvoid*)((char*)buf->m_fixedBuffer.ptr() + buf->m_mappedOffset); |
| 3144 | } |
| 3145 | |
| 3146 | static const char* const kNameDelimiter = ";"; |
| 3147 | |
| 3148 | static std::string packVarNames(GLsizei count, const char** names, GLint* err_out) { |
| 3149 | |
| 3150 | #define VALIDATE(cond, err) if (cond) { *err_out = err; return packed; } \ |
| 3151 | |
| 3152 | std::string packed; |
| 3153 | // validate the array of char[]'s |
| 3154 | const char* currName; |
| 3155 | for (GLsizei i = 0; i < count; i++) { |
| 3156 | currName = names[i]; |
| 3157 | VALIDATE(!currName, GL_INVALID_OPERATION); |
| 3158 | // check if has reasonable size |
| 3159 | size_t len = strlen(currName); |
| 3160 | VALIDATE(!len, GL_INVALID_OPERATION); |
| 3161 | // check for our delimiter, which if present |
| 3162 | // in the name, means an invalid name anyway. |
| 3163 | VALIDATE(strstr(currName, kNameDelimiter), |
| 3164 | GL_INVALID_OPERATION); |
| 3165 | packed += currName; |
| 3166 | packed += ";"; |
| 3167 | } |
| 3168 | |
| 3169 | *err_out = GL_NO_ERROR; |
| 3170 | return packed; |
| 3171 | } |
| 3172 | |
| 3173 | void GL2Encoder::s_glGetUniformIndices(void* self, GLuint program, GLsizei uniformCount, const GLchar ** uniformNames, GLuint* uniformIndices) { |
| 3174 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 3175 | |
| 3176 | if (!uniformCount) return; |
| 3177 | |
| 3178 | GLint err = GL_NO_ERROR; |
| 3179 | std::string packed = packVarNames(uniformCount, (const char**)uniformNames, &err); |
| 3180 | SET_ERROR_IF(err != GL_NO_ERROR, GL_INVALID_OPERATION); |
| 3181 | |
| 3182 | bool needLocationWAR = ctx->m_shared->needUniformLocationWAR(program); |
| 3183 | std::vector<int> arrIndices; |
| 3184 | for (size_t i = 0; i < uniformCount; i++) { |
| 3185 | int err; |
| 3186 | arrIndices.push_back(sArrIndexOfUniformExpr(uniformNames[i], &err)); |
| 3187 | if (err) { |
| 3188 | ALOGE("%s: invalid uniform name %s!", __FUNCTION__, uniformNames[i]); |
| 3189 | return; |
| 3190 | } |
| 3191 | } |
| 3192 | |
| 3193 | ctx->glGetUniformIndicesAEMU(ctx, program, uniformCount, (const GLchar*)&packed[0], packed.size() + 1, uniformIndices); |
| 3194 | |
| 3195 | for (int i = 0; i < uniformCount; i++) { |
| 3196 | if (uniformIndices[i] >= 0 && needLocationWAR) { |
| 3197 | uniformIndices[i] = |
| 3198 | ctx->m_shared->locationWARHostToApp(program, uniformIndices[i], arrIndices[i]); |
| 3199 | } |
| 3200 | } |
| 3201 | } |
| 3202 | |
| 3203 | void GL2Encoder::s_glUniform1ui(void* self, GLint location, GLuint v0) { |
| 3204 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 3205 | GLClientState* state = ctx->m_state; |
| 3206 | GLSharedGroupPtr shared = ctx->m_shared; |
| 3207 | |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 3208 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 3209 | ctx->m_glUniform1ui_enc(self, hostLoc, v0); |
| 3210 | |
| 3211 | GLenum target; |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 3212 | if (shared->setSamplerUniform(state->currentShaderProgram(), location, v0, &target)) { |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 3213 | GLenum origActiveTexture = state->getActiveTextureUnit(); |
| 3214 | if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + v0, target)) { |
| 3215 | ctx->m_glActiveTexture_enc(self, origActiveTexture); |
| 3216 | } |
| 3217 | state->setActiveTextureUnit(origActiveTexture); |
| 3218 | } |
| 3219 | } |
| 3220 | |
| 3221 | void GL2Encoder::s_glUniform2ui(void* self, GLint location, GLuint v0, GLuint v1) { |
| 3222 | GL2Encoder *ctx = (GL2Encoder*)self; |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 3223 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 3224 | ctx->m_glUniform2ui_enc(self, hostLoc, v0, v1); |
| 3225 | } |
| 3226 | |
| 3227 | void GL2Encoder::s_glUniform3ui(void* self, GLint location, GLuint v0, GLuint v1, GLuint v2) { |
| 3228 | GL2Encoder *ctx = (GL2Encoder*)self; |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 3229 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 3230 | ctx->m_glUniform3ui_enc(self, hostLoc, v0, v1, v2); |
| 3231 | } |
| 3232 | |
| 3233 | void GL2Encoder::s_glUniform4ui(void* self, GLint location, GLint v0, GLuint v1, GLuint v2, GLuint v3) { |
| 3234 | GL2Encoder *ctx = (GL2Encoder*)self; |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 3235 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 3236 | ctx->m_glUniform4ui_enc(self, hostLoc, v0, v1, v2, v3); |
| 3237 | } |
| 3238 | |
| 3239 | void GL2Encoder::s_glUniform1uiv(void* self, GLint location, GLsizei count, const GLuint *value) { |
| 3240 | GL2Encoder *ctx = (GL2Encoder*)self; |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 3241 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 3242 | ctx->m_glUniform1uiv_enc(self, hostLoc, count, value); |
| 3243 | } |
| 3244 | |
| 3245 | void GL2Encoder::s_glUniform2uiv(void* self, GLint location, GLsizei count, const GLuint *value) { |
| 3246 | GL2Encoder *ctx = (GL2Encoder*)self; |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 3247 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 3248 | ctx->m_glUniform2uiv_enc(self, hostLoc, count, value); |
| 3249 | } |
| 3250 | |
| 3251 | void GL2Encoder::s_glUniform3uiv(void* self, GLint location, GLsizei count, const GLuint *value) { |
| 3252 | GL2Encoder *ctx = (GL2Encoder*)self; |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 3253 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 3254 | ctx->m_glUniform3uiv_enc(self, hostLoc, count, value); |
| 3255 | } |
| 3256 | |
| 3257 | void GL2Encoder::s_glUniform4uiv(void* self, GLint location, GLsizei count, const GLuint *value) { |
| 3258 | GL2Encoder *ctx = (GL2Encoder*)self; |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 3259 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 3260 | ctx->m_glUniform4uiv_enc(self, hostLoc, count, value); |
| 3261 | } |
| 3262 | |
| 3263 | void GL2Encoder::s_glUniformMatrix2x3fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { |
| 3264 | GL2Encoder *ctx = (GL2Encoder*)self; |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 3265 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 3266 | ctx->m_glUniformMatrix2x3fv_enc(self, hostLoc, count, transpose, value); |
| 3267 | } |
| 3268 | |
| 3269 | void GL2Encoder::s_glUniformMatrix3x2fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { |
| 3270 | GL2Encoder *ctx = (GL2Encoder*)self; |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 3271 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 3272 | ctx->m_glUniformMatrix3x2fv_enc(self, hostLoc, count, transpose, value); |
| 3273 | } |
| 3274 | |
| 3275 | void GL2Encoder::s_glUniformMatrix2x4fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { |
| 3276 | GL2Encoder *ctx = (GL2Encoder*)self; |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 3277 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 3278 | ctx->m_glUniformMatrix2x4fv_enc(self, hostLoc, count, transpose, value); |
| 3279 | } |
| 3280 | |
| 3281 | void GL2Encoder::s_glUniformMatrix4x2fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { |
| 3282 | GL2Encoder *ctx = (GL2Encoder*)self; |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 3283 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 3284 | ctx->m_glUniformMatrix4x2fv_enc(self, hostLoc, count, transpose, value); |
| 3285 | } |
| 3286 | |
| 3287 | void GL2Encoder::s_glUniformMatrix3x4fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { |
| 3288 | GL2Encoder *ctx = (GL2Encoder*)self; |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 3289 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 3290 | ctx->m_glUniformMatrix3x4fv_enc(self, hostLoc, count, transpose, value); |
| 3291 | } |
| 3292 | |
| 3293 | void GL2Encoder::s_glUniformMatrix4x3fv(void* self, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { |
| 3294 | GL2Encoder *ctx = (GL2Encoder*)self; |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 3295 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentShaderProgram(),location); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 3296 | ctx->m_glUniformMatrix4x3fv_enc(self, hostLoc, count, transpose, value); |
| 3297 | } |
| 3298 | |
| 3299 | void GL2Encoder::s_glGetUniformuiv(void* self, GLuint program, GLint location, GLuint* params) { |
| 3300 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 3301 | SET_ERROR_IF(!ctx->m_shared->isShaderOrProgramObject(program), GL_INVALID_VALUE); |
| 3302 | SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION); |
| 3303 | SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION); |
| 3304 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location); |
| 3305 | SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION); |
| 3306 | ctx->m_glGetUniformuiv_enc(self, program, hostLoc, params); |
| 3307 | } |
| 3308 | |
| 3309 | void GL2Encoder::s_glGetActiveUniformBlockiv(void* self, GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params) { |
| 3310 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 3311 | GLClientState* state = ctx->m_state; |
| 3312 | |
| 3313 | // refresh client state's # active uniforms in this block |
| 3314 | if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES) { |
| 3315 | // TODO if worth it: cache uniform count and other params, |
| 3316 | // invalidate on program relinking. |
| 3317 | GLint numActiveUniforms; |
| 3318 | ctx->m_glGetActiveUniformBlockiv_enc(ctx, |
| 3319 | program, uniformBlockIndex, |
| 3320 | GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, |
| 3321 | &numActiveUniforms); |
| 3322 | ctx->m_state->setNumActiveUniformsInUniformBlock( |
| 3323 | program, uniformBlockIndex, numActiveUniforms); |
| 3324 | } |
| 3325 | |
| 3326 | ctx->m_glGetActiveUniformBlockiv_enc(ctx, |
| 3327 | program, uniformBlockIndex, |
| 3328 | pname, params); |
| 3329 | } |
| 3330 | |
| 3331 | void GL2Encoder::s_glGetVertexAttribIiv(void* self, GLuint index, GLenum pname, GLint* params) { |
| 3332 | GL2Encoder *ctx = (GL2Encoder *)self; |
| 3333 | assert(ctx->m_state); |
| 3334 | GLint maxIndex; |
| 3335 | ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex); |
| 3336 | SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE); |
| 3337 | |
| 3338 | if (!ctx->m_state->getVertexAttribParameter<GLint>(index, pname, params)) { |
| 3339 | ctx->m_glGetVertexAttribIiv_enc(self, index, pname, params); |
| 3340 | } |
| 3341 | } |
| 3342 | |
| 3343 | void GL2Encoder::s_glGetVertexAttribIuiv(void* self, GLuint index, GLenum pname, GLuint* params) { |
| 3344 | GL2Encoder *ctx = (GL2Encoder *)self; |
| 3345 | assert(ctx->m_state); |
| 3346 | GLint maxIndex; |
| 3347 | ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex); |
| 3348 | SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE); |
| 3349 | |
| 3350 | if (!ctx->m_state->getVertexAttribParameter<GLuint>(index, pname, params)) { |
| 3351 | ctx->m_glGetVertexAttribIuiv_enc(self, index, pname, params); |
| 3352 | } |
| 3353 | } |
| 3354 | |
| 3355 | void GL2Encoder::s_glVertexAttribIPointer(void* self, GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer) { |
| 3356 | GL2Encoder *ctx = (GL2Encoder *)self; |
| 3357 | assert(ctx->m_state != NULL); |
Lingfeng Yang | 0728990 | 2017-01-27 12:26:19 -0800 | [diff] [blame] | 3358 | VALIDATE_VERTEX_ATTRIB_INDEX(index); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 3359 | SET_ERROR_IF((size < 1 || size > 4), GL_INVALID_VALUE); |
| 3360 | SET_ERROR_IF( |
| 3361 | !(type == GL_BYTE || |
| 3362 | type == GL_UNSIGNED_BYTE || |
| 3363 | type == GL_SHORT || |
| 3364 | type == GL_UNSIGNED_SHORT || |
| 3365 | type == GL_INT || |
| 3366 | type == GL_UNSIGNED_INT), |
| 3367 | GL_INVALID_ENUM); |
| 3368 | SET_ERROR_IF(stride < 0, GL_INVALID_VALUE); |
| 3369 | |
| 3370 | ctx->m_state->setVertexAttribBinding(index, index); |
| 3371 | ctx->m_state->setVertexAttribFormat(index, size, type, false, 0, true); |
| 3372 | GLsizei effectiveStride = stride; |
| 3373 | if (stride == 0) { |
| 3374 | effectiveStride = glSizeof(type) * size; |
| 3375 | } |
| 3376 | ctx->m_state->bindIndexedBuffer(0, index, ctx->m_state->currentArrayVbo(), (uintptr_t)pointer, 0, stride, effectiveStride); |
| 3377 | |
| 3378 | if (ctx->m_state->currentArrayVbo() != 0) { |
| 3379 | ctx->glVertexAttribIPointerOffsetAEMU(ctx, index, size, type, stride, (uintptr_t)pointer); |
| 3380 | } else { |
| 3381 | SET_ERROR_IF(ctx->m_state->currentVertexArrayObject() != 0 && pointer, GL_INVALID_OPERATION); |
| 3382 | // wait for client-array handler |
| 3383 | } |
| 3384 | } |
| 3385 | |
| 3386 | void GL2Encoder::s_glVertexAttribDivisor(void* self, GLuint index, GLuint divisor) { |
| 3387 | GL2Encoder *ctx = (GL2Encoder *)self; |
| 3388 | assert(ctx->m_state != NULL); |
Lingfeng Yang | 0728990 | 2017-01-27 12:26:19 -0800 | [diff] [blame] | 3389 | VALIDATE_VERTEX_ATTRIB_INDEX(index); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 3390 | ctx->m_state->setVertexAttribBinding(index, index); |
| 3391 | ctx->m_state->setVertexBindingDivisor(index, divisor); |
| 3392 | ctx->m_glVertexAttribDivisor_enc(ctx, index, divisor); |
| 3393 | } |
| 3394 | |
| 3395 | void GL2Encoder::s_glRenderbufferStorageMultisample(void* self, |
| 3396 | GLenum target, GLsizei samples, GLenum internalformat, |
| 3397 | GLsizei width, GLsizei height) { |
| 3398 | GL2Encoder *ctx = (GL2Encoder *)self; |
| 3399 | GLClientState* state = ctx->m_state; |
| 3400 | |
| 3401 | SET_ERROR_IF(target != GL_RENDERBUFFER, GL_INVALID_ENUM); |
| 3402 | SET_ERROR_IF(!GLESv2Validation::rboFormat(ctx, internalformat), GL_INVALID_ENUM); |
| 3403 | |
| 3404 | GLint max_samples; |
| 3405 | ctx->s_glGetInternalformativ(ctx, target, internalformat, GL_SAMPLES, 1, &max_samples); |
| 3406 | SET_ERROR_IF(samples > max_samples, GL_INVALID_OPERATION); |
| 3407 | |
| 3408 | state->setBoundRenderbufferFormat(internalformat); |
| 3409 | state->setBoundRenderbufferSamples(samples); |
| 3410 | ctx->m_glRenderbufferStorageMultisample_enc( |
| 3411 | self, target, samples, internalformat, width, height); |
| 3412 | } |
| 3413 | |
| 3414 | void GL2Encoder::s_glDrawBuffers(void* self, GLsizei n, const GLenum* bufs) { |
| 3415 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 3416 | SET_ERROR_IF(!ctx->m_state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) && n > 1, GL_INVALID_OPERATION); |
| 3417 | SET_ERROR_IF(n < 0 || n > ctx->m_state->getMaxDrawBuffers(), GL_INVALID_VALUE); |
| 3418 | for (int i = 0; i < n; i++) { |
| 3419 | SET_ERROR_IF( |
| 3420 | bufs[i] != GL_NONE && |
| 3421 | bufs[i] != GL_BACK && |
| 3422 | glUtilsColorAttachmentIndex(bufs[i]) == -1, |
| 3423 | GL_INVALID_ENUM); |
| 3424 | SET_ERROR_IF( |
| 3425 | !ctx->m_state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) && |
| 3426 | glUtilsColorAttachmentIndex(bufs[i]) != -1, |
| 3427 | GL_INVALID_OPERATION); |
| 3428 | SET_ERROR_IF( |
| 3429 | ctx->m_state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) && |
| 3430 | ((glUtilsColorAttachmentIndex(bufs[i]) != -1 && |
| 3431 | glUtilsColorAttachmentIndex(bufs[i]) != i) || |
| 3432 | (glUtilsColorAttachmentIndex(bufs[i]) == -1 && |
| 3433 | bufs[i] != GL_NONE)), |
| 3434 | GL_INVALID_OPERATION); |
| 3435 | } |
| 3436 | |
| 3437 | ctx->m_glDrawBuffers_enc(ctx, n, bufs); |
| 3438 | } |
| 3439 | |
| 3440 | void GL2Encoder::s_glReadBuffer(void* self, GLenum src) { |
| 3441 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 3442 | |
| 3443 | SET_ERROR_IF( |
| 3444 | glUtilsColorAttachmentIndex(src) != -1 && |
| 3445 | (glUtilsColorAttachmentIndex(src) >= |
| 3446 | ctx->m_state->getMaxColorAttachments()), |
| 3447 | GL_INVALID_OPERATION); |
| 3448 | SET_ERROR_IF( |
| 3449 | src != GL_NONE && |
| 3450 | src != GL_BACK && |
| 3451 | src > GL_COLOR_ATTACHMENT0 && |
| 3452 | src < GL_DEPTH_ATTACHMENT && |
| 3453 | (src - GL_COLOR_ATTACHMENT0) > |
| 3454 | ctx->m_state->getMaxColorAttachments(), |
| 3455 | GL_INVALID_OPERATION); |
| 3456 | SET_ERROR_IF( |
| 3457 | src != GL_NONE && |
| 3458 | src != GL_BACK && |
| 3459 | glUtilsColorAttachmentIndex(src) == -1, |
| 3460 | GL_INVALID_ENUM); |
| 3461 | SET_ERROR_IF( |
| 3462 | !ctx->m_state->boundFramebuffer(GL_READ_FRAMEBUFFER) && |
| 3463 | src != GL_NONE && |
| 3464 | src != GL_BACK, |
| 3465 | GL_INVALID_OPERATION); |
| 3466 | SET_ERROR_IF( |
| 3467 | ctx->m_state->boundFramebuffer(GL_READ_FRAMEBUFFER) && |
| 3468 | src != GL_NONE && |
| 3469 | glUtilsColorAttachmentIndex(src) == -1, |
| 3470 | GL_INVALID_OPERATION); |
| 3471 | |
| 3472 | ctx->m_glReadBuffer_enc(ctx, src); |
| 3473 | } |
| 3474 | |
| 3475 | void GL2Encoder::s_glFramebufferTextureLayer(void* self, GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) { |
| 3476 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 3477 | GLClientState* state = ctx->m_state; |
| 3478 | |
| 3479 | SET_ERROR_IF(!GLESv2Validation::framebufferTarget(ctx, target), GL_INVALID_ENUM); |
| 3480 | SET_ERROR_IF(!GLESv2Validation::framebufferAttachment(ctx, attachment), GL_INVALID_ENUM); |
| 3481 | GLenum lastBoundTarget = state->queryTexLastBoundTarget(texture); |
| 3482 | SET_ERROR_IF(lastBoundTarget != GL_TEXTURE_2D_ARRAY && |
| 3483 | lastBoundTarget != GL_TEXTURE_3D, |
| 3484 | GL_INVALID_OPERATION); |
| 3485 | state->attachTextureObject(target, attachment, texture); |
| 3486 | |
| 3487 | GLint max3DTextureSize; |
| 3488 | ctx->glGetIntegerv(ctx, GL_MAX_3D_TEXTURE_SIZE, &max3DTextureSize); |
| 3489 | SET_ERROR_IF( |
| 3490 | layer >= max3DTextureSize, |
| 3491 | GL_INVALID_VALUE); |
| 3492 | |
| 3493 | ctx->m_glFramebufferTextureLayer_enc(self, target, attachment, texture, level, layer); |
| 3494 | } |
| 3495 | |
| 3496 | void GL2Encoder::s_glTexStorage2D(void* self, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) { |
| 3497 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 3498 | GLClientState* state = ctx->m_state; |
| 3499 | |
| 3500 | SET_ERROR_IF( |
| 3501 | target != GL_TEXTURE_2D && |
| 3502 | target != GL_TEXTURE_CUBE_MAP, |
| 3503 | GL_INVALID_ENUM); |
| 3504 | SET_ERROR_IF(!GLESv2Validation::pixelInternalFormat(internalformat), GL_INVALID_ENUM); |
| 3505 | SET_ERROR_IF(!state->getBoundTexture(target), GL_INVALID_OPERATION); |
| 3506 | SET_ERROR_IF(levels < 1 || width < 1 || height < 1, GL_INVALID_VALUE); |
| 3507 | SET_ERROR_IF(levels > ilog2((uint32_t)std::max(width, height)) + 1, |
| 3508 | GL_INVALID_OPERATION); |
| 3509 | SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION); |
| 3510 | |
| 3511 | state->setBoundTextureInternalFormat(target, internalformat); |
| 3512 | state->setBoundTextureDims(target, -1, width, height, 1); |
| 3513 | state->setBoundTextureImmutableFormat(target); |
Lingfeng Yang | a9fff6a | 2018-03-02 13:42:51 -0800 | [diff] [blame] | 3514 | |
| 3515 | if (target == GL_TEXTURE_2D) { |
| 3516 | ctx->override2DTextureTarget(target); |
| 3517 | } |
| 3518 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 3519 | ctx->m_glTexStorage2D_enc(ctx, target, levels, internalformat, width, height); |
Lingfeng Yang | a9fff6a | 2018-03-02 13:42:51 -0800 | [diff] [blame] | 3520 | |
| 3521 | if (target == GL_TEXTURE_2D) { |
| 3522 | ctx->restore2DTextureTarget(target); |
| 3523 | } |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 3524 | } |
| 3525 | |
| 3526 | void GL2Encoder::s_glTransformFeedbackVaryings(void* self, GLuint program, GLsizei count, const char** varyings, GLenum bufferMode) { |
| 3527 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 3528 | |
| 3529 | SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_VALUE); |
| 3530 | |
| 3531 | GLint maxCount = 0; |
| 3532 | ctx->glGetIntegerv(ctx, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &maxCount); |
| 3533 | |
| 3534 | SET_ERROR_IF( |
| 3535 | bufferMode == GL_SEPARATE_ATTRIBS && |
| 3536 | maxCount < count, |
| 3537 | GL_INVALID_VALUE); |
| 3538 | SET_ERROR_IF( |
| 3539 | bufferMode != GL_INTERLEAVED_ATTRIBS && |
| 3540 | bufferMode != GL_SEPARATE_ATTRIBS, |
| 3541 | GL_INVALID_ENUM); |
| 3542 | |
| 3543 | if (!count) return; |
| 3544 | |
| 3545 | GLint err = GL_NO_ERROR; |
| 3546 | std::string packed = packVarNames(count, varyings, &err); |
| 3547 | SET_ERROR_IF(err != GL_NO_ERROR, GL_INVALID_OPERATION); |
| 3548 | |
| 3549 | ctx->glTransformFeedbackVaryingsAEMU(ctx, program, count, (const char*)&packed[0], packed.size() + 1, bufferMode); |
| 3550 | } |
| 3551 | |
| 3552 | void GL2Encoder::s_glBeginTransformFeedback(void* self, GLenum primitiveMode) { |
| 3553 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 3554 | GLClientState* state = ctx->m_state; |
| 3555 | ctx->m_glBeginTransformFeedback_enc(ctx, primitiveMode); |
| 3556 | state->setTransformFeedbackActiveUnpaused(true); |
| 3557 | } |
| 3558 | |
| 3559 | void GL2Encoder::s_glEndTransformFeedback(void* self) { |
| 3560 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 3561 | GLClientState* state = ctx->m_state; |
| 3562 | ctx->m_glEndTransformFeedback_enc(ctx); |
| 3563 | state->setTransformFeedbackActiveUnpaused(false); |
| 3564 | } |
| 3565 | |
| 3566 | void GL2Encoder::s_glPauseTransformFeedback(void* self) { |
| 3567 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 3568 | GLClientState* state = ctx->m_state; |
| 3569 | ctx->m_glPauseTransformFeedback_enc(ctx); |
| 3570 | state->setTransformFeedbackActiveUnpaused(false); |
| 3571 | } |
| 3572 | |
| 3573 | void GL2Encoder::s_glResumeTransformFeedback(void* self) { |
| 3574 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 3575 | GLClientState* state = ctx->m_state; |
| 3576 | ctx->m_glResumeTransformFeedback_enc(ctx); |
| 3577 | state->setTransformFeedbackActiveUnpaused(true); |
| 3578 | } |
| 3579 | |
| 3580 | void GL2Encoder::s_glTexImage3D(void* self, GLenum target, GLint level, GLint internalFormat, |
| 3581 | GLsizei width, GLsizei height, GLsizei depth, |
| 3582 | GLint border, GLenum format, GLenum type, const GLvoid* data) { |
| 3583 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 3584 | GLClientState* state = ctx->m_state; |
| 3585 | |
| 3586 | SET_ERROR_IF(target != GL_TEXTURE_3D && |
| 3587 | target != GL_TEXTURE_2D_ARRAY, |
| 3588 | GL_INVALID_ENUM); |
| 3589 | SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM); |
| 3590 | SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM); |
| 3591 | |
| 3592 | // If unpack buffer is nonzero, verify unmapped state. |
| 3593 | SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION); |
| 3594 | |
| 3595 | GLint max_texture_size; |
| 3596 | GLint max_3d_texture_size; |
| 3597 | ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size); |
| 3598 | ctx->glGetIntegerv(ctx, GL_MAX_3D_TEXTURE_SIZE, &max_3d_texture_size); |
| 3599 | SET_ERROR_IF(level < 0, GL_INVALID_VALUE); |
| 3600 | SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE); |
| 3601 | SET_ERROR_IF(level > ilog2(max_3d_texture_size), GL_INVALID_VALUE); |
| 3602 | |
| 3603 | SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE); |
| 3604 | SET_ERROR_IF(width > GL_MAX_TEXTURE_SIZE, GL_INVALID_VALUE); |
| 3605 | SET_ERROR_IF(height > GL_MAX_TEXTURE_SIZE, GL_INVALID_VALUE); |
| 3606 | SET_ERROR_IF(depth > GL_MAX_TEXTURE_SIZE, GL_INVALID_VALUE); |
| 3607 | SET_ERROR_IF(width > GL_MAX_3D_TEXTURE_SIZE, GL_INVALID_VALUE); |
| 3608 | SET_ERROR_IF(height > GL_MAX_3D_TEXTURE_SIZE, GL_INVALID_VALUE); |
| 3609 | SET_ERROR_IF(depth > GL_MAX_3D_TEXTURE_SIZE, GL_INVALID_VALUE); |
| 3610 | SET_ERROR_IF(border != 0, GL_INVALID_VALUE); |
| 3611 | // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type. |
| 3612 | SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) && |
| 3613 | ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) && |
| 3614 | (ctx->m_state->pboNeededDataSize(width, height, depth, format, type, 0) > |
| 3615 | ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size), |
| 3616 | GL_INVALID_OPERATION); |
| 3617 | SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) && |
| 3618 | ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) && |
| 3619 | (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size % |
| 3620 | glSizeof(type)), |
| 3621 | GL_INVALID_OPERATION); |
| 3622 | SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION); |
| 3623 | |
| 3624 | state->setBoundTextureInternalFormat(target, internalFormat); |
| 3625 | state->setBoundTextureFormat(target, format); |
| 3626 | state->setBoundTextureType(target, type); |
| 3627 | state->setBoundTextureDims(target, level, width, height, depth); |
| 3628 | |
| 3629 | if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) { |
| 3630 | ctx->glTexImage3DOffsetAEMU( |
| 3631 | ctx, target, level, internalFormat, |
| 3632 | width, height, depth, |
| 3633 | border, format, type, (uintptr_t)data); |
| 3634 | } else { |
| 3635 | ctx->m_glTexImage3D_enc(ctx, |
| 3636 | target, level, internalFormat, |
| 3637 | width, height, depth, |
| 3638 | border, format, type, data); |
| 3639 | } |
| 3640 | } |
| 3641 | |
| 3642 | void GL2Encoder::s_glTexSubImage3D(void* self, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* data) { |
| 3643 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 3644 | GLClientState* state = ctx->m_state; |
| 3645 | |
| 3646 | SET_ERROR_IF(target != GL_TEXTURE_3D && |
| 3647 | target != GL_TEXTURE_2D_ARRAY, |
| 3648 | GL_INVALID_ENUM); |
| 3649 | SET_ERROR_IF(!GLESv2Validation::pixelType(ctx, type), GL_INVALID_ENUM); |
| 3650 | SET_ERROR_IF(!GLESv2Validation::pixelFormat(ctx, format), GL_INVALID_ENUM); |
| 3651 | // If unpack buffer is nonzero, verify unmapped state. |
| 3652 | SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION); |
| 3653 | GLint max_texture_size; |
| 3654 | GLint max_3d_texture_size; |
| 3655 | ctx->glGetIntegerv(ctx, GL_MAX_TEXTURE_SIZE, &max_texture_size); |
| 3656 | ctx->glGetIntegerv(ctx, GL_MAX_3D_TEXTURE_SIZE, &max_3d_texture_size); |
| 3657 | SET_ERROR_IF(level < 0, GL_INVALID_VALUE); |
| 3658 | SET_ERROR_IF(level > ilog2(max_texture_size), GL_INVALID_VALUE); |
| 3659 | SET_ERROR_IF(level > ilog2(max_3d_texture_size), GL_INVALID_VALUE); |
| 3660 | SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE); |
| 3661 | SET_ERROR_IF(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE); |
| 3662 | GLuint tex = state->getBoundTexture(target); |
| 3663 | GLsizei neededWidth = xoffset + width; |
| 3664 | GLsizei neededHeight = yoffset + height; |
| 3665 | GLsizei neededDepth = zoffset + depth; |
| 3666 | |
| 3667 | SET_ERROR_IF(tex && |
| 3668 | (neededWidth > state->queryTexWidth(level, tex) || |
| 3669 | neededHeight > state->queryTexHeight(level, tex) || |
| 3670 | neededDepth > state->queryTexDepth(level, tex)), |
| 3671 | GL_INVALID_VALUE); |
| 3672 | // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type. |
| 3673 | SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) && |
| 3674 | ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) && |
| 3675 | (ctx->m_state->pboNeededDataSize(width, height, depth, format, type, 0) > |
| 3676 | ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size), |
| 3677 | GL_INVALID_OPERATION); |
| 3678 | SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) && |
| 3679 | ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) && |
| 3680 | (ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size % |
| 3681 | glSizeof(type)), |
| 3682 | GL_INVALID_OPERATION); |
| 3683 | SET_ERROR_IF(!ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) && !data, GL_INVALID_OPERATION); |
| 3684 | SET_ERROR_IF(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE); |
| 3685 | |
| 3686 | if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) { |
| 3687 | ctx->glTexSubImage3DOffsetAEMU(ctx, |
| 3688 | target, level, |
| 3689 | xoffset, yoffset, zoffset, |
| 3690 | width, height, depth, |
| 3691 | format, type, (uintptr_t)data); |
| 3692 | } else { |
| 3693 | ctx->m_glTexSubImage3D_enc(ctx, |
| 3694 | target, level, |
| 3695 | xoffset, yoffset, zoffset, |
| 3696 | width, height, depth, |
| 3697 | format, type, data); |
| 3698 | } |
| 3699 | } |
| 3700 | |
| 3701 | void GL2Encoder::s_glCompressedTexImage3D(void* self, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data) { |
| 3702 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 3703 | GLClientState* state = ctx->m_state; |
| 3704 | |
| 3705 | // Filter compressed formats support. |
| 3706 | SET_ERROR_IF(!GLESv2Validation::supportedCompressedFormat(ctx, internalformat), GL_INVALID_ENUM); |
| 3707 | // If unpack buffer is nonzero, verify unmapped state. |
| 3708 | SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION); |
| 3709 | SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE); |
| 3710 | SET_ERROR_IF(border, GL_INVALID_VALUE); |
| 3711 | // If unpack buffer is nonzero, verify buffer data fits. |
| 3712 | SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) && |
| 3713 | ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) && |
| 3714 | (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size), |
| 3715 | GL_INVALID_OPERATION); |
| 3716 | // TODO: Fix: |
| 3717 | // If |imageSize| is too small for compressed dimensions. |
| 3718 | // SET_ERROR_IF(GLESv2Validation::compressedTexImageSize(internalformat, width, height, depth) > imageSize, GL_INVALID_VALUE); |
| 3719 | state->setBoundTextureInternalFormat(target, (GLint)internalformat); |
| 3720 | state->setBoundTextureDims(target, level, width, height, depth); |
| 3721 | |
| 3722 | if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) { |
| 3723 | ctx->glCompressedTexImage3DOffsetAEMU( |
| 3724 | ctx, target, level, internalformat, |
| 3725 | width, height, depth, border, |
| 3726 | imageSize, (uintptr_t)data); |
| 3727 | } else { |
| 3728 | ctx->m_glCompressedTexImage3D_enc( |
| 3729 | ctx, target, level, internalformat, |
| 3730 | width, height, depth, border, |
| 3731 | imageSize, data); |
| 3732 | } |
| 3733 | } |
| 3734 | |
| 3735 | void GL2Encoder::s_glCompressedTexSubImage3D(void* self, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data) { |
| 3736 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 3737 | GLClientState* state = ctx->m_state; |
| 3738 | |
| 3739 | SET_ERROR_IF(!GLESv2Validation::textureTarget(ctx, target), GL_INVALID_ENUM); |
| 3740 | // If unpack buffer is nonzero, verify unmapped state. |
| 3741 | SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_UNPACK_BUFFER), GL_INVALID_OPERATION); |
| 3742 | SET_ERROR_IF(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE); |
| 3743 | // If unpack buffer is nonzero, verify buffer data fits. |
| 3744 | SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) && |
| 3745 | ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) && |
| 3746 | (imageSize > ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size), |
| 3747 | GL_INVALID_OPERATION); |
| 3748 | SET_ERROR_IF(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE); |
| 3749 | |
| 3750 | if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) { |
| 3751 | ctx->glCompressedTexSubImage3DOffsetAEMU( |
| 3752 | ctx, target, level, |
| 3753 | xoffset, yoffset, zoffset, |
| 3754 | width, height, depth, |
| 3755 | format, imageSize, (uintptr_t)data); |
| 3756 | } else { |
| 3757 | ctx->m_glCompressedTexSubImage3D_enc( |
| 3758 | ctx, target, level, |
| 3759 | xoffset, yoffset, zoffset, |
| 3760 | width, height, depth, |
| 3761 | format, imageSize, data); |
| 3762 | |
| 3763 | } |
| 3764 | } |
| 3765 | |
| 3766 | void GL2Encoder::s_glTexStorage3D(void* self, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) { |
| 3767 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 3768 | GLClientState* state = ctx->m_state; |
| 3769 | SET_ERROR_IF(target != GL_TEXTURE_3D && |
| 3770 | target != GL_TEXTURE_2D_ARRAY, |
| 3771 | GL_INVALID_ENUM); |
| 3772 | SET_ERROR_IF(!GLESv2Validation::pixelInternalFormat(internalformat), GL_INVALID_ENUM); |
| 3773 | SET_ERROR_IF(!state->getBoundTexture(target), GL_INVALID_OPERATION); |
| 3774 | SET_ERROR_IF(levels < 1 || width < 1 || height < 1, GL_INVALID_VALUE); |
| 3775 | SET_ERROR_IF(target == GL_TEXTURE_3D && (levels > ilog2((uint32_t)std::max(width, std::max(height, depth))) + 1), |
| 3776 | GL_INVALID_OPERATION); |
| 3777 | SET_ERROR_IF(target == GL_TEXTURE_2D_ARRAY && (levels > ilog2((uint32_t)std::max(width, height)) + 1), |
| 3778 | GL_INVALID_OPERATION); |
| 3779 | SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION); |
| 3780 | |
| 3781 | state->setBoundTextureInternalFormat(target, internalformat); |
| 3782 | state->setBoundTextureDims(target, -1, width, height, depth); |
| 3783 | state->setBoundTextureImmutableFormat(target); |
| 3784 | ctx->m_glTexStorage3D_enc(ctx, target, levels, internalformat, width, height, depth); |
| 3785 | state->setBoundTextureImmutableFormat(target); |
| 3786 | } |
| 3787 | |
| 3788 | void GL2Encoder::s_glDrawArraysInstanced(void* self, GLenum mode, GLint first, GLsizei count, GLsizei primcount) { |
| 3789 | GL2Encoder *ctx = (GL2Encoder *)self; |
| 3790 | assert(ctx->m_state != NULL); |
| 3791 | SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM); |
| 3792 | SET_ERROR_IF(count < 0, GL_INVALID_VALUE); |
| 3793 | |
| 3794 | bool has_client_vertex_arrays = false; |
| 3795 | bool has_indirect_arrays = false; |
| 3796 | ctx->getVBOUsage(&has_client_vertex_arrays, |
| 3797 | &has_indirect_arrays); |
| 3798 | |
| 3799 | if (has_client_vertex_arrays || |
| 3800 | (!has_client_vertex_arrays && |
| 3801 | !has_indirect_arrays)) { |
| 3802 | ctx->sendVertexAttributes(first, count, true, primcount); |
| 3803 | ctx->m_glDrawArraysInstanced_enc(ctx, mode, 0, count, primcount); |
| 3804 | } else { |
| 3805 | ctx->sendVertexAttributes(0, count, false, primcount); |
| 3806 | ctx->m_glDrawArraysInstanced_enc(ctx, mode, first, count, primcount); |
| 3807 | } |
| 3808 | ctx->m_stream->flush(); |
| 3809 | } |
| 3810 | |
| 3811 | void GL2Encoder::s_glDrawElementsInstanced(void* self, GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei primcount) |
| 3812 | { |
| 3813 | |
| 3814 | GL2Encoder *ctx = (GL2Encoder *)self; |
| 3815 | assert(ctx->m_state != NULL); |
| 3816 | SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM); |
| 3817 | SET_ERROR_IF(count < 0, GL_INVALID_VALUE); |
| 3818 | SET_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT), GL_INVALID_ENUM); |
| 3819 | SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION); |
| 3820 | |
| 3821 | bool has_client_vertex_arrays = false; |
| 3822 | bool has_indirect_arrays = false; |
| 3823 | int nLocations = ctx->m_state->nLocations(); |
| 3824 | GLintptr offset = 0; |
| 3825 | |
| 3826 | ctx->getVBOUsage(&has_client_vertex_arrays, &has_indirect_arrays); |
| 3827 | |
| 3828 | if (!has_client_vertex_arrays && !has_indirect_arrays) { |
| 3829 | // ALOGW("glDrawElements: no vertex arrays / buffers bound to the command\n"); |
| 3830 | GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER); |
| 3831 | SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION); |
| 3832 | } |
| 3833 | |
| 3834 | BufferData* buf = NULL; |
| 3835 | int minIndex = 0, maxIndex = 0; |
| 3836 | |
| 3837 | // For validation/immediate index array purposes, |
| 3838 | // we need the min/max vertex index of the index array. |
| 3839 | // If the VBO != 0, this may not be the first time we have |
| 3840 | // used this particular index buffer. getBufferIndexRange |
| 3841 | // can more quickly get min/max vertex index by |
| 3842 | // caching previous results. |
| 3843 | if (ctx->m_state->currentIndexVbo() != 0) { |
| 3844 | buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo()); |
| 3845 | offset = (GLintptr)indices; |
| 3846 | indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices); |
| 3847 | ctx->getBufferIndexRange(buf, |
| 3848 | indices, |
| 3849 | type, |
| 3850 | (size_t)count, |
| 3851 | (size_t)offset, |
| 3852 | &minIndex, &maxIndex); |
| 3853 | } else { |
| 3854 | // In this case, the |indices| field holds a real |
| 3855 | // array, so calculate the indices now. They will |
| 3856 | // also be needed to know how much data to |
| 3857 | // transfer to host. |
| 3858 | ctx->calcIndexRange(indices, |
| 3859 | type, |
| 3860 | count, |
| 3861 | &minIndex, |
| 3862 | &maxIndex); |
| 3863 | } |
| 3864 | |
| 3865 | bool adjustIndices = true; |
| 3866 | if (ctx->m_state->currentIndexVbo() != 0) { |
| 3867 | if (!has_client_vertex_arrays) { |
| 3868 | ctx->sendVertexAttributes(0, maxIndex + 1, false, primcount); |
| 3869 | ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo()); |
| 3870 | ctx->glDrawElementsInstancedOffsetAEMU(ctx, mode, count, type, offset, primcount); |
| 3871 | ctx->flushDrawCall(); |
| 3872 | adjustIndices = false; |
| 3873 | } else { |
| 3874 | BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo()); |
| 3875 | ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0); |
| 3876 | } |
| 3877 | } |
| 3878 | if (adjustIndices) { |
| 3879 | void *adjustedIndices = |
| 3880 | ctx->recenterIndices(indices, |
| 3881 | type, |
| 3882 | count, |
| 3883 | minIndex); |
| 3884 | |
| 3885 | if (has_indirect_arrays || 1) { |
| 3886 | ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1, true, primcount); |
| 3887 | ctx->glDrawElementsInstancedDataAEMU(ctx, mode, count, type, adjustedIndices, primcount, count * glSizeof(type)); |
| 3888 | ctx->m_stream->flush(); |
| 3889 | // XXX - OPTIMIZATION (see the other else branch) should be implemented |
| 3890 | if(!has_indirect_arrays) { |
| 3891 | //ALOGD("unoptimized drawelements !!!\n"); |
| 3892 | } |
| 3893 | } else { |
| 3894 | // we are all direct arrays and immidate mode index array - |
| 3895 | // rebuild the arrays and the index array; |
| 3896 | ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n"); |
| 3897 | } |
| 3898 | } |
| 3899 | } |
| 3900 | |
| 3901 | void GL2Encoder::s_glDrawRangeElements(void* self, GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void* indices) |
| 3902 | { |
| 3903 | |
| 3904 | GL2Encoder *ctx = (GL2Encoder *)self; |
| 3905 | assert(ctx->m_state != NULL); |
| 3906 | SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM); |
| 3907 | SET_ERROR_IF(end < start, GL_INVALID_VALUE); |
| 3908 | SET_ERROR_IF(count < 0, GL_INVALID_VALUE); |
| 3909 | SET_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT), GL_INVALID_ENUM); |
| 3910 | SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION); |
| 3911 | |
| 3912 | bool has_client_vertex_arrays = false; |
| 3913 | bool has_indirect_arrays = false; |
| 3914 | int nLocations = ctx->m_state->nLocations(); |
| 3915 | GLintptr offset = 0; |
| 3916 | |
| 3917 | ctx->getVBOUsage(&has_client_vertex_arrays, &has_indirect_arrays); |
| 3918 | |
| 3919 | if (!has_client_vertex_arrays && !has_indirect_arrays) { |
| 3920 | // ALOGW("glDrawElements: no vertex arrays / buffers bound to the command\n"); |
| 3921 | GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER); |
| 3922 | SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION); |
| 3923 | } |
| 3924 | |
| 3925 | BufferData* buf = NULL; |
| 3926 | int minIndex = 0, maxIndex = 0; |
| 3927 | |
| 3928 | // For validation/immediate index array purposes, |
| 3929 | // we need the min/max vertex index of the index array. |
| 3930 | // If the VBO != 0, this may not be the first time we have |
| 3931 | // used this particular index buffer. getBufferIndexRange |
| 3932 | // can more quickly get min/max vertex index by |
| 3933 | // caching previous results. |
| 3934 | if (ctx->m_state->currentIndexVbo() != 0) { |
| 3935 | buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo()); |
| 3936 | offset = (GLintptr)indices; |
| 3937 | indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices); |
| 3938 | ctx->getBufferIndexRange(buf, |
| 3939 | indices, |
| 3940 | type, |
| 3941 | (size_t)count, |
| 3942 | (size_t)offset, |
| 3943 | &minIndex, &maxIndex); |
| 3944 | } else { |
| 3945 | // In this case, the |indices| field holds a real |
| 3946 | // array, so calculate the indices now. They will |
| 3947 | // also be needed to know how much data to |
| 3948 | // transfer to host. |
| 3949 | ctx->calcIndexRange(indices, |
| 3950 | type, |
| 3951 | count, |
| 3952 | &minIndex, |
| 3953 | &maxIndex); |
| 3954 | } |
| 3955 | |
| 3956 | bool adjustIndices = true; |
| 3957 | if (ctx->m_state->currentIndexVbo() != 0) { |
| 3958 | if (!has_client_vertex_arrays) { |
| 3959 | ctx->sendVertexAttributes(0, maxIndex + 1, false); |
| 3960 | ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo()); |
| 3961 | ctx->glDrawElementsOffset(ctx, mode, count, type, offset); |
| 3962 | ctx->flushDrawCall(); |
| 3963 | adjustIndices = false; |
| 3964 | } else { |
| 3965 | BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo()); |
| 3966 | ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0); |
| 3967 | } |
| 3968 | } |
| 3969 | if (adjustIndices) { |
| 3970 | void *adjustedIndices = |
| 3971 | ctx->recenterIndices(indices, |
| 3972 | type, |
| 3973 | count, |
| 3974 | minIndex); |
| 3975 | |
| 3976 | if (has_indirect_arrays || 1) { |
| 3977 | ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1, true); |
| 3978 | ctx->glDrawElementsData(ctx, mode, count, type, adjustedIndices, count * glSizeof(type)); |
| 3979 | ctx->m_stream->flush(); |
| 3980 | // XXX - OPTIMIZATION (see the other else branch) should be implemented |
| 3981 | if(!has_indirect_arrays) { |
| 3982 | //ALOGD("unoptimized drawelements !!!\n"); |
| 3983 | } |
| 3984 | } else { |
| 3985 | // we are all direct arrays and immidate mode index array - |
| 3986 | // rebuild the arrays and the index array; |
| 3987 | ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n"); |
| 3988 | } |
| 3989 | } |
| 3990 | } |
| 3991 | |
| 3992 | // struct GLStringKey { |
| 3993 | // GLenum name; |
| 3994 | // GLuint index; |
| 3995 | // }; |
| 3996 | // |
| 3997 | // struct GLStringKeyCompare { |
| 3998 | // bool operator() (const GLStringKey& a, |
| 3999 | // const GLStringKey& b) const { |
| 4000 | // if (a.name != b.name) return a.name < b.name; |
| 4001 | // if (a.index != b.index) return a.index < b.index; |
| 4002 | // return false; |
| 4003 | // } |
| 4004 | // }; |
| 4005 | // |
| 4006 | // typedef std::map<GLStringKey, std::string, GLStringKeyCompare> GLStringStore; |
| 4007 | // |
| 4008 | // static GLStringStore sGLStringStore; |
| 4009 | // bool sGLStringStoreInitialized = false; |
| 4010 | |
| 4011 | const GLubyte* GL2Encoder::s_glGetStringi(void* self, GLenum name, GLuint index) { |
| 4012 | GL2Encoder *ctx = (GL2Encoder *)self; |
Lingfeng Yang | a16eb2e | 2018-02-23 11:26:53 -0800 | [diff] [blame] | 4013 | const GLubyte *retval = (GLubyte *) ""; |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 4014 | |
| 4015 | RET_AND_SET_ERROR_IF( |
| 4016 | name != GL_VENDOR && |
| 4017 | name != GL_RENDERER && |
| 4018 | name != GL_VERSION && |
| 4019 | name != GL_EXTENSIONS, |
| 4020 | GL_INVALID_ENUM, |
| 4021 | retval); |
| 4022 | |
| 4023 | RET_AND_SET_ERROR_IF( |
| 4024 | name == GL_VENDOR || |
| 4025 | name == GL_RENDERER || |
| 4026 | name == GL_VERSION || |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 4027 | index != 0, |
| 4028 | GL_INVALID_VALUE, |
| 4029 | retval); |
| 4030 | |
Lingfeng Yang | a16eb2e | 2018-02-23 11:26:53 -0800 | [diff] [blame] | 4031 | RET_AND_SET_ERROR_IF( |
| 4032 | name == GL_EXTENSIONS && |
| 4033 | index >= ctx->m_currExtensionsArray.size(), |
| 4034 | GL_INVALID_VALUE, |
| 4035 | retval); |
| 4036 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 4037 | switch (name) { |
| 4038 | case GL_VENDOR: |
| 4039 | retval = gVendorString; |
| 4040 | break; |
| 4041 | case GL_RENDERER: |
| 4042 | retval = gRendererString; |
| 4043 | break; |
| 4044 | case GL_VERSION: |
| 4045 | retval = gVersionString; |
| 4046 | break; |
| 4047 | case GL_EXTENSIONS: |
Lingfeng Yang | a16eb2e | 2018-02-23 11:26:53 -0800 | [diff] [blame] | 4048 | retval = (const GLubyte*)(ctx->m_currExtensionsArray[index].c_str()); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 4049 | break; |
| 4050 | } |
| 4051 | |
| 4052 | return retval; |
| 4053 | } |
| 4054 | |
| 4055 | void GL2Encoder::s_glGetProgramBinary(void* self, GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, void* binary) { |
| 4056 | GL2Encoder *ctx = (GL2Encoder *)self; |
| 4057 | |
| 4058 | SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION); |
| 4059 | |
| 4060 | GLint linkStatus = 0; |
| 4061 | ctx->glGetProgramiv(self, program, GL_LINK_STATUS, &linkStatus); |
| 4062 | GLint properLength = 0; |
| 4063 | ctx->glGetProgramiv(self, program, GL_PROGRAM_BINARY_LENGTH, &properLength); |
| 4064 | |
| 4065 | SET_ERROR_IF(!linkStatus, GL_INVALID_OPERATION); |
| 4066 | SET_ERROR_IF(bufSize < properLength, GL_INVALID_OPERATION); |
| 4067 | |
| 4068 | ctx->m_glGetProgramBinary_enc(ctx, program, bufSize, length, binaryFormat, binary); |
| 4069 | } |
| 4070 | |
| 4071 | void GL2Encoder::s_glReadPixels(void* self, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) { |
| 4072 | GL2Encoder *ctx = (GL2Encoder *)self; |
| 4073 | |
| 4074 | SET_ERROR_IF(!GLESv2Validation::readPixelsFormat(format), GL_INVALID_ENUM); |
| 4075 | SET_ERROR_IF(!GLESv2Validation::readPixelsType(type), GL_INVALID_ENUM); |
| 4076 | SET_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE); |
| 4077 | SET_ERROR_IF(ctx->isBufferTargetMapped(GL_PIXEL_PACK_BUFFER), GL_INVALID_OPERATION); |
| 4078 | SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_PACK_BUFFER) && |
| 4079 | ctx->getBufferData(GL_PIXEL_PACK_BUFFER) && |
| 4080 | (ctx->m_state->pboNeededDataSize(width, height, 1, format, type, 1) > |
| 4081 | ctx->getBufferData(GL_PIXEL_PACK_BUFFER)->m_size), |
| 4082 | GL_INVALID_OPERATION); |
| 4083 | /* |
| 4084 | GL_INVALID_OPERATION is generated if the readbuffer of the currently bound framebuffer is a fixed point normalized surface and format and type are neither GL_RGBA and GL_UNSIGNED_BYTE, respectively, nor the format/type pair returned by querying GL_IMPLEMENTATION_COLOR_READ_FORMAT and GL_IMPLEMENTATION_COLOR_READ_TYPE. |
| 4085 | |
| 4086 | GL_INVALID_OPERATION is generated if the readbuffer of the currently bound framebuffer is a floating point surface and format and type are neither GL_RGBA and GL_FLOAT, respectively, nor the format/type pair returned by querying GL_IMPLEMENTATION_COLOR_READ_FORMAT and GL_IMPLEMENTATION_COLOR_READ_TYPE. |
| 4087 | |
| 4088 | GL_INVALID_OPERATION is generated if the readbuffer of the currently bound framebuffer is a signed integer surface and format and type are neither GL_RGBA_INTEGER and GL_INT, respectively, nor the format/type pair returned by querying GL_IMPLEMENTATION_COLOR_READ_FORMAT and GL_IMPLEMENTATION_COLOR_READ_TYPE. |
| 4089 | |
| 4090 | GL_INVALID_OPERATION is generated if the readbuffer of the currently bound framebuffer is an unsigned integer surface and format and type are neither GL_RGBA_INTEGER and GL_UNSIGNED_INT, respectively, nor the format/type pair returned by querying GL_IMPLEMENTATION_COLOR_READ_FORMAT and GL_IMPLEMENTATION_COLOR_READ_TYPE. |
| 4091 | */ |
| 4092 | |
| 4093 | FboFormatInfo fbo_format_info; |
| 4094 | ctx->m_state->getBoundFramebufferFormat( |
| 4095 | GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &fbo_format_info); |
| 4096 | SET_ERROR_IF( |
| 4097 | fbo_format_info.type == FBO_ATTACHMENT_TEXTURE && |
| 4098 | !GLESv2Validation::readPixelsFboFormatMatch( |
| 4099 | format, type, fbo_format_info.tex_type), |
| 4100 | GL_INVALID_OPERATION); |
| 4101 | |
| 4102 | if (ctx->boundBuffer(GL_PIXEL_PACK_BUFFER)) { |
| 4103 | ctx->glReadPixelsOffsetAEMU( |
| 4104 | ctx, x, y, width, height, |
| 4105 | format, type, (uintptr_t)pixels); |
| 4106 | } else { |
| 4107 | ctx->m_glReadPixels_enc( |
| 4108 | ctx, x, y, width, height, |
| 4109 | format, type, pixels); |
| 4110 | } |
| 4111 | } |
| 4112 | |
| 4113 | // Track enabled state for some things like: |
| 4114 | // - Primitive restart |
| 4115 | void GL2Encoder::s_glEnable(void* self, GLenum what) { |
| 4116 | GL2Encoder *ctx = (GL2Encoder *)self; |
| 4117 | |
| 4118 | switch (what) { |
| 4119 | case GL_PRIMITIVE_RESTART_FIXED_INDEX: |
| 4120 | ctx->m_primitiveRestartEnabled = true; |
| 4121 | break; |
| 4122 | } |
| 4123 | |
| 4124 | ctx->m_glEnable_enc(ctx, what); |
| 4125 | } |
| 4126 | |
| 4127 | void GL2Encoder::s_glDisable(void* self, GLenum what) { |
| 4128 | GL2Encoder *ctx = (GL2Encoder *)self; |
| 4129 | |
| 4130 | switch (what) { |
| 4131 | case GL_PRIMITIVE_RESTART_FIXED_INDEX: |
| 4132 | ctx->m_primitiveRestartEnabled = false; |
| 4133 | break; |
| 4134 | } |
| 4135 | |
| 4136 | ctx->m_glDisable_enc(ctx, what); |
| 4137 | } |
| 4138 | |
| 4139 | void GL2Encoder::s_glClearBufferiv(void* self, GLenum buffer, GLint drawBuffer, const GLint * value) { |
| 4140 | GL2Encoder *ctx = (GL2Encoder *)self; |
| 4141 | |
| 4142 | SET_ERROR_IF(buffer == GL_DEPTH || buffer == GL_DEPTH_STENCIL, GL_INVALID_ENUM); |
| 4143 | |
| 4144 | ctx->m_glClearBufferiv_enc(ctx, buffer, drawBuffer, value); |
| 4145 | } |
| 4146 | |
| 4147 | void GL2Encoder::s_glClearBufferuiv(void* self, GLenum buffer, GLint drawBuffer, const GLuint * value) { |
| 4148 | GL2Encoder *ctx = (GL2Encoder *)self; |
| 4149 | |
| 4150 | SET_ERROR_IF(buffer == GL_DEPTH || buffer == GL_STENCIL || buffer == GL_DEPTH_STENCIL, GL_INVALID_ENUM); |
| 4151 | |
| 4152 | ctx->m_glClearBufferuiv_enc(ctx, buffer, drawBuffer, value); |
| 4153 | } |
| 4154 | |
| 4155 | void GL2Encoder::s_glClearBufferfv(void* self, GLenum buffer, GLint drawBuffer, const GLfloat * value) { |
| 4156 | GL2Encoder *ctx = (GL2Encoder *)self; |
| 4157 | |
| 4158 | SET_ERROR_IF(buffer == GL_STENCIL || buffer == GL_DEPTH_STENCIL, GL_INVALID_ENUM); |
| 4159 | |
| 4160 | ctx->m_glClearBufferfv_enc(ctx, buffer, drawBuffer, value); |
| 4161 | } |
| 4162 | |
| 4163 | void GL2Encoder::s_glBlitFramebuffer(void* self, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) { |
| 4164 | GL2Encoder *ctx = (GL2Encoder *)self; |
| 4165 | GLClientState* state = ctx->m_state; |
| 4166 | |
| 4167 | bool validateColor = mask | GL_COLOR_BUFFER_BIT; |
| 4168 | bool validateDepth = mask | GL_DEPTH_BUFFER_BIT; |
| 4169 | bool validateStencil = mask | GL_STENCIL_BUFFER_BIT; |
| 4170 | |
| 4171 | FboFormatInfo read_fbo_format_info; |
| 4172 | FboFormatInfo draw_fbo_format_info; |
| 4173 | if (validateColor) { |
| 4174 | state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &read_fbo_format_info); |
| 4175 | state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &draw_fbo_format_info); |
| 4176 | |
| 4177 | if (read_fbo_format_info.type == FBO_ATTACHMENT_TEXTURE && |
| 4178 | draw_fbo_format_info.type == FBO_ATTACHMENT_TEXTURE) { |
| 4179 | SET_ERROR_IF( |
| 4180 | state->boundFramebuffer(GL_READ_FRAMEBUFFER) && |
| 4181 | state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) && |
| 4182 | !GLESv2Validation::blitFramebufferFormat( |
| 4183 | read_fbo_format_info.tex_type, |
| 4184 | draw_fbo_format_info.tex_type), |
| 4185 | GL_INVALID_OPERATION); |
| 4186 | } |
| 4187 | } |
| 4188 | |
| 4189 | if (validateDepth) { |
| 4190 | state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, &read_fbo_format_info); |
| 4191 | state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, &draw_fbo_format_info); |
| 4192 | |
| 4193 | if (read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER && |
| 4194 | draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER) { |
| 4195 | SET_ERROR_IF( |
| 4196 | state->boundFramebuffer(GL_READ_FRAMEBUFFER) && |
| 4197 | state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) && |
| 4198 | !GLESv2Validation::blitFramebufferFormat( |
| 4199 | read_fbo_format_info.rb_format, |
| 4200 | draw_fbo_format_info.rb_format), |
| 4201 | GL_INVALID_OPERATION); |
| 4202 | } |
| 4203 | } |
| 4204 | |
| 4205 | if (validateStencil) { |
| 4206 | state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, &read_fbo_format_info); |
| 4207 | state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, &draw_fbo_format_info); |
| 4208 | |
| 4209 | if (read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER && |
| 4210 | draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER) { |
| 4211 | SET_ERROR_IF( |
| 4212 | state->boundFramebuffer(GL_READ_FRAMEBUFFER) && |
| 4213 | state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) && |
| 4214 | !GLESv2Validation::blitFramebufferFormat( |
| 4215 | read_fbo_format_info.rb_format, |
| 4216 | draw_fbo_format_info.rb_format), |
| 4217 | GL_INVALID_OPERATION); |
| 4218 | } |
| 4219 | } |
| 4220 | |
| 4221 | state->getBoundFramebufferFormat(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &draw_fbo_format_info); |
| 4222 | SET_ERROR_IF( |
| 4223 | draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER && |
| 4224 | draw_fbo_format_info.rb_multisamples > 0, |
| 4225 | GL_INVALID_OPERATION); |
| 4226 | SET_ERROR_IF( |
| 4227 | draw_fbo_format_info.type == FBO_ATTACHMENT_TEXTURE && |
| 4228 | draw_fbo_format_info.tex_multisamples > 0, |
| 4229 | GL_INVALID_OPERATION); |
| 4230 | |
| 4231 | state->getBoundFramebufferFormat(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &read_fbo_format_info); |
| 4232 | SET_ERROR_IF( |
| 4233 | read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER && |
| 4234 | read_fbo_format_info.rb_multisamples > 0 && |
| 4235 | draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER && |
| 4236 | state->boundFramebuffer(GL_READ_FRAMEBUFFER) && |
| 4237 | state->boundFramebuffer(GL_DRAW_FRAMEBUFFER) && |
| 4238 | (read_fbo_format_info.rb_format != |
| 4239 | draw_fbo_format_info.rb_format), |
| 4240 | GL_INVALID_OPERATION); |
| 4241 | SET_ERROR_IF( |
| 4242 | read_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER && |
| 4243 | read_fbo_format_info.rb_multisamples > 0 && |
| 4244 | draw_fbo_format_info.type == FBO_ATTACHMENT_RENDERBUFFER && |
| 4245 | (srcX0 != dstX0 || srcY0 != dstY0 || |
| 4246 | srcX1 != dstX1 || srcY1 != dstY1), |
| 4247 | GL_INVALID_OPERATION); |
| 4248 | |
| 4249 | ctx->m_glBlitFramebuffer_enc(ctx, |
| 4250 | srcX0, srcY0, srcX1, srcY1, |
| 4251 | dstX0, dstY0, dstX1, dstY1, |
| 4252 | mask, filter); |
| 4253 | } |
| 4254 | |
| 4255 | void GL2Encoder::s_glGetInternalformativ(void* self, GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params) { |
| 4256 | GL2Encoder *ctx = (GL2Encoder *)self; |
| 4257 | |
| 4258 | SET_ERROR_IF(pname != GL_NUM_SAMPLE_COUNTS && |
| 4259 | pname != GL_SAMPLES, |
| 4260 | GL_INVALID_ENUM); |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 4261 | SET_ERROR_IF(!GLESv2Validation::internalFormatTarget(ctx, target), GL_INVALID_ENUM); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 4262 | SET_ERROR_IF(!GLESv2Validation::unsizedFormat(internalformat) && |
Lingfeng Yang | 931817b | 2017-01-27 06:50:56 -0800 | [diff] [blame] | 4263 | !GLESv2Validation::colorRenderableFormat(ctx, internalformat) && |
| 4264 | !GLESv2Validation::depthRenderableFormat(ctx, internalformat) && |
| 4265 | !GLESv2Validation::stencilRenderableFormat(ctx, internalformat), |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 4266 | GL_INVALID_ENUM); |
| 4267 | SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE); |
| 4268 | |
| 4269 | if (bufSize < 1) return; |
| 4270 | |
| 4271 | // Desktop OpenGL can allow a mindboggling # samples per pixel (such as 64). |
| 4272 | // Limit to 4 (spec minimum) to keep dEQP tests from timing out. |
| 4273 | switch (pname) { |
| 4274 | case GL_NUM_SAMPLE_COUNTS: |
| 4275 | *params = 3; |
| 4276 | break; |
| 4277 | case GL_SAMPLES: |
| 4278 | params[0] = 4; |
| 4279 | if (bufSize > 1) params[1] = 2; |
| 4280 | if (bufSize > 2) params[2] = 1; |
| 4281 | break; |
| 4282 | default: |
| 4283 | break; |
| 4284 | } |
| 4285 | } |
| 4286 | |
| 4287 | void GL2Encoder::s_glGenerateMipmap(void* self, GLenum target) { |
| 4288 | GL2Encoder *ctx = (GL2Encoder *)self; |
| 4289 | GLClientState* state = ctx->m_state; |
| 4290 | |
| 4291 | SET_ERROR_IF(target != GL_TEXTURE_2D && |
| 4292 | target != GL_TEXTURE_3D && |
Yahan Zhou | 53c6458 | 2018-04-16 15:46:17 -0700 | [diff] [blame] | 4293 | target != GL_TEXTURE_CUBE_MAP && |
| 4294 | target != GL_TEXTURE_2D_ARRAY, |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 4295 | GL_INVALID_ENUM); |
| 4296 | |
| 4297 | GLuint tex = state->getBoundTexture(target); |
| 4298 | GLenum internalformat = state->queryTexInternalFormat(tex); |
| 4299 | GLenum format = state->queryTexFormat(tex); |
| 4300 | |
| 4301 | SET_ERROR_IF(tex && GLESv2Validation::isCompressedFormat(internalformat), |
| 4302 | GL_INVALID_OPERATION); |
| 4303 | SET_ERROR_IF(tex && |
| 4304 | !GLESv2Validation::unsizedFormat(internalformat) && |
Lingfeng Yang | 931817b | 2017-01-27 06:50:56 -0800 | [diff] [blame] | 4305 | !(GLESv2Validation::colorRenderableFormat(ctx, internalformat) && |
| 4306 | GLESv2Validation::filterableTexFormat(ctx, internalformat)), |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 4307 | GL_INVALID_OPERATION); |
| 4308 | |
Lingfeng Yang | a9fff6a | 2018-03-02 13:42:51 -0800 | [diff] [blame] | 4309 | if (target == GL_TEXTURE_2D) { |
| 4310 | ctx->override2DTextureTarget(target); |
| 4311 | } |
| 4312 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 4313 | ctx->m_glGenerateMipmap_enc(ctx, target); |
Lingfeng Yang | a9fff6a | 2018-03-02 13:42:51 -0800 | [diff] [blame] | 4314 | |
| 4315 | if (target == GL_TEXTURE_2D) { |
| 4316 | ctx->restore2DTextureTarget(target); |
| 4317 | } |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 4318 | } |
| 4319 | |
| 4320 | void GL2Encoder::s_glBindSampler(void* self, GLuint unit, GLuint sampler) { |
| 4321 | GL2Encoder *ctx = (GL2Encoder *)self; |
| 4322 | GLint maxCombinedUnits; |
| 4323 | ctx->glGetIntegerv(ctx, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxCombinedUnits); |
| 4324 | SET_ERROR_IF(unit >= maxCombinedUnits, GL_INVALID_VALUE); |
| 4325 | |
| 4326 | ctx->m_glBindSampler_enc(ctx, unit, sampler); |
| 4327 | } |
| 4328 | |
Lingfeng Yang | f000ab4 | 2017-01-11 18:31:38 -0800 | [diff] [blame] | 4329 | GLsync GL2Encoder::s_glFenceSync(void* self, GLenum condition, GLbitfield flags) { |
| 4330 | GL2Encoder *ctx = (GL2Encoder *)self; |
| 4331 | uint64_t syncHandle = ctx->glFenceSyncAEMU(ctx, condition, flags); |
| 4332 | return (GLsync)(uintptr_t)syncHandle; |
| 4333 | } |
| 4334 | |
| 4335 | GLenum GL2Encoder::s_glClientWaitSync(void* self, GLsync wait_on, GLbitfield flags, GLuint64 timeout) { |
| 4336 | GL2Encoder *ctx = (GL2Encoder *)self; |
| 4337 | return ctx->glClientWaitSyncAEMU(ctx, (uint64_t)(uintptr_t)wait_on, flags, timeout); |
| 4338 | } |
| 4339 | |
| 4340 | void GL2Encoder::s_glWaitSync(void* self, GLsync wait_on, GLbitfield flags, GLuint64 timeout) { |
| 4341 | GL2Encoder *ctx = (GL2Encoder *)self; |
| 4342 | ctx->glWaitSyncAEMU(ctx, (uint64_t)(uintptr_t)wait_on, flags, timeout); |
| 4343 | } |
| 4344 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 4345 | void GL2Encoder::s_glDeleteSync(void* self, GLsync sync) { |
| 4346 | GL2Encoder *ctx = (GL2Encoder *)self; |
| 4347 | |
| 4348 | if (!sync) return; |
| 4349 | |
Lingfeng Yang | f000ab4 | 2017-01-11 18:31:38 -0800 | [diff] [blame] | 4350 | ctx->glDeleteSyncAEMU(ctx, (uint64_t)(uintptr_t)sync); |
| 4351 | } |
| 4352 | |
| 4353 | GLboolean GL2Encoder::s_glIsSync(void* self, GLsync sync) { |
| 4354 | GL2Encoder *ctx = (GL2Encoder *)self; |
| 4355 | return ctx->glIsSyncAEMU(ctx, (uint64_t)(uintptr_t)sync); |
| 4356 | } |
| 4357 | |
| 4358 | void GL2Encoder::s_glGetSynciv(void* self, GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values) { |
| 4359 | GL2Encoder *ctx = (GL2Encoder *)self; |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 4360 | |
| 4361 | SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE); |
| 4362 | |
Lingfeng Yang | f000ab4 | 2017-01-11 18:31:38 -0800 | [diff] [blame] | 4363 | return ctx->glGetSyncivAEMU(ctx, (uint64_t)(uintptr_t)sync, pname, bufSize, length, values); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 4364 | } |
| 4365 | |
| 4366 | #define LIMIT_CASE(target, lim) \ |
| 4367 | case target: \ |
| 4368 | ctx->glGetIntegerv(ctx, lim, &limit); \ |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 4369 | SET_ERROR_IF(index < 0 || index >= limit, GL_INVALID_VALUE); \ |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 4370 | break; \ |
| 4371 | |
| 4372 | void GL2Encoder::s_glGetIntegeri_v(void* self, GLenum target, GLuint index, GLint* params) { |
| 4373 | GL2Encoder *ctx = (GL2Encoder *)self; |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 4374 | GLClientState* state = ctx->m_state; |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 4375 | |
| 4376 | GLint limit; |
| 4377 | |
| 4378 | switch (target) { |
| 4379 | LIMIT_CASE(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS) |
| 4380 | LIMIT_CASE(GL_UNIFORM_BUFFER_BINDING, GL_MAX_UNIFORM_BUFFER_BINDINGS) |
| 4381 | LIMIT_CASE(GL_ATOMIC_COUNTER_BUFFER_BINDING, GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS) |
| 4382 | LIMIT_CASE(GL_SHADER_STORAGE_BUFFER_BINDING, GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS) |
| 4383 | default: |
| 4384 | break; |
| 4385 | } |
| 4386 | |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 4387 | const GLClientState::VertexAttribBindingVector& currBindings = |
| 4388 | state->currentVertexBufferBindings(); |
| 4389 | |
| 4390 | switch (target) { |
| 4391 | case GL_VERTEX_BINDING_DIVISOR: |
| 4392 | case GL_VERTEX_BINDING_OFFSET: |
| 4393 | case GL_VERTEX_BINDING_STRIDE: |
| 4394 | case GL_VERTEX_BINDING_BUFFER: |
| 4395 | SET_ERROR_IF(index < 0 || index > currBindings.size(), GL_INVALID_VALUE); |
| 4396 | break; |
| 4397 | default: |
| 4398 | break; |
| 4399 | } |
| 4400 | |
| 4401 | switch (target) { |
| 4402 | case GL_VERTEX_BINDING_DIVISOR: |
| 4403 | *params = currBindings[index].divisor; |
| 4404 | return; |
| 4405 | case GL_VERTEX_BINDING_OFFSET: |
| 4406 | *params = currBindings[index].offset; |
| 4407 | return; |
| 4408 | case GL_VERTEX_BINDING_STRIDE: |
| 4409 | *params = currBindings[index].effectiveStride; |
| 4410 | return; |
| 4411 | case GL_VERTEX_BINDING_BUFFER: |
| 4412 | *params = currBindings[index].buffer; |
| 4413 | return; |
| 4414 | default: |
| 4415 | break; |
| 4416 | } |
| 4417 | |
Lingfeng Yang | 80a3633 | 2017-07-09 10:58:07 -0700 | [diff] [blame] | 4418 | ctx->safe_glGetIntegeri_v(target, index, params); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 4419 | } |
| 4420 | |
| 4421 | void GL2Encoder::s_glGetInteger64i_v(void* self, GLenum target, GLuint index, GLint64* params) { |
| 4422 | GL2Encoder *ctx = (GL2Encoder *)self; |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 4423 | GLClientState* state = ctx->m_state; |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 4424 | |
| 4425 | GLint limit; |
| 4426 | |
| 4427 | switch (target) { |
| 4428 | LIMIT_CASE(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS) |
| 4429 | LIMIT_CASE(GL_UNIFORM_BUFFER_BINDING, GL_MAX_UNIFORM_BUFFER_BINDINGS) |
| 4430 | LIMIT_CASE(GL_ATOMIC_COUNTER_BUFFER_BINDING, GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS) |
| 4431 | LIMIT_CASE(GL_SHADER_STORAGE_BUFFER_BINDING, GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS) |
| 4432 | default: |
| 4433 | break; |
| 4434 | } |
| 4435 | |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 4436 | const GLClientState::VertexAttribBindingVector& currBindings = |
| 4437 | state->currentVertexBufferBindings(); |
| 4438 | |
| 4439 | switch (target) { |
| 4440 | case GL_VERTEX_BINDING_DIVISOR: |
| 4441 | case GL_VERTEX_BINDING_OFFSET: |
| 4442 | case GL_VERTEX_BINDING_STRIDE: |
| 4443 | case GL_VERTEX_BINDING_BUFFER: |
| 4444 | SET_ERROR_IF(index < 0 || index > currBindings.size(), GL_INVALID_VALUE); |
| 4445 | break; |
| 4446 | default: |
| 4447 | break; |
| 4448 | } |
| 4449 | |
| 4450 | switch (target) { |
| 4451 | case GL_VERTEX_BINDING_DIVISOR: |
| 4452 | *params = currBindings[index].divisor; |
| 4453 | return; |
| 4454 | case GL_VERTEX_BINDING_OFFSET: |
| 4455 | *params = currBindings[index].offset; |
| 4456 | return; |
| 4457 | case GL_VERTEX_BINDING_STRIDE: |
| 4458 | *params = currBindings[index].effectiveStride; |
| 4459 | return; |
| 4460 | case GL_VERTEX_BINDING_BUFFER: |
| 4461 | *params = currBindings[index].buffer; |
| 4462 | return; |
| 4463 | default: |
| 4464 | break; |
| 4465 | } |
| 4466 | |
Lingfeng Yang | 80a3633 | 2017-07-09 10:58:07 -0700 | [diff] [blame] | 4467 | ctx->safe_glGetInteger64i_v(target, index, params); |
| 4468 | } |
| 4469 | |
| 4470 | void GL2Encoder::s_glGetInteger64v(void* self, GLenum param, GLint64* val) { |
| 4471 | GL2Encoder *ctx = (GL2Encoder *)self; |
| 4472 | ctx->safe_glGetInteger64v(param, val); |
| 4473 | } |
| 4474 | |
| 4475 | void GL2Encoder::s_glGetBooleani_v(void* self, GLenum param, GLuint index, GLboolean* val) { |
| 4476 | GL2Encoder *ctx = (GL2Encoder *)self; |
| 4477 | ctx->safe_glGetBooleani_v(param, index, val); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 4478 | } |
| 4479 | |
| 4480 | void GL2Encoder::s_glGetShaderiv(void* self, GLuint shader, GLenum pname, GLint* params) { |
| 4481 | GL2Encoder *ctx = (GL2Encoder *)self; |
| 4482 | ctx->m_glGetShaderiv_enc(self, shader, pname, params); |
| 4483 | if (pname == GL_SHADER_SOURCE_LENGTH) { |
| 4484 | ShaderData* shaderData = ctx->m_shared->getShaderData(shader); |
| 4485 | if (shaderData) { |
| 4486 | int totalLen = 0; |
| 4487 | for (int i = 0; i < shaderData->sources.size(); i++) { |
| 4488 | totalLen += shaderData->sources[i].size(); |
| 4489 | } |
| 4490 | if (totalLen != 0) { |
| 4491 | *params = totalLen + 1; // account for null terminator |
| 4492 | } |
| 4493 | } |
| 4494 | } |
| 4495 | } |
| 4496 | |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 4497 | void GL2Encoder::s_glActiveShaderProgram(void* self, GLuint pipeline, GLuint program) { |
| 4498 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4499 | GLClientState* state = ctx->m_state; |
| 4500 | GLSharedGroupPtr shared = ctx->m_shared; |
| 4501 | |
| 4502 | SET_ERROR_IF(!pipeline, GL_INVALID_OPERATION); |
| 4503 | SET_ERROR_IF(program && !shared->isShaderOrProgramObject(program), GL_INVALID_VALUE); |
| 4504 | SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION); |
| 4505 | |
| 4506 | ctx->m_glActiveShaderProgram_enc(ctx, pipeline, program); |
| 4507 | if (!state->currentProgram()) { |
| 4508 | state->setCurrentShaderProgram(program); |
| 4509 | } |
| 4510 | } |
| 4511 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 4512 | GLuint GL2Encoder::s_glCreateShaderProgramv(void* self, GLenum type, GLsizei count, const char** strings) { |
| 4513 | |
| 4514 | GLint* length = NULL; |
| 4515 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 4516 | |
| 4517 | int len = glUtilsCalcShaderSourceLen((char**)strings, length, count); |
| 4518 | char *str = new char[len + 1]; |
| 4519 | glUtilsPackStrings(str, (char**)strings, (GLint*)length, count); |
| 4520 | |
| 4521 | // Do GLSharedGroup and location WorkARound-specific initialization |
| 4522 | // Phase 1: create a ShaderData and initialize with replaceSamplerExternalWith2D() |
| 4523 | uint32_t spDataId = ctx->m_shared->addNewShaderProgramData(); |
| 4524 | ShaderProgramData* spData = ctx->m_shared->getShaderProgramDataById(spDataId); |
| 4525 | ShaderData* sData = spData->shaderData; |
| 4526 | |
| 4527 | if (!replaceSamplerExternalWith2D(str, sData)) { |
| 4528 | delete [] str; |
| 4529 | ctx->setError(GL_OUT_OF_MEMORY); |
| 4530 | ctx->m_shared->deleteShaderProgramDataById(spDataId); |
| 4531 | return -1; |
| 4532 | } |
| 4533 | |
| 4534 | GLuint res = ctx->glCreateShaderProgramvAEMU(ctx, type, count, str, len + 1); |
| 4535 | delete [] str; |
| 4536 | |
| 4537 | // Phase 2: do glLinkProgram-related initialization for locationWorkARound |
| 4538 | GLint linkStatus = 0; |
| 4539 | ctx->glGetProgramiv(self, res, GL_LINK_STATUS ,&linkStatus); |
| 4540 | if (!linkStatus) { |
| 4541 | ctx->m_shared->deleteShaderProgramDataById(spDataId); |
| 4542 | return -1; |
| 4543 | } |
| 4544 | |
| 4545 | ctx->m_shared->associateGLShaderProgram(res, spDataId); |
| 4546 | |
| 4547 | GLint numUniforms = 0; |
Lingfeng Yang | 80a3633 | 2017-07-09 10:58:07 -0700 | [diff] [blame] | 4548 | ctx->glGetProgramiv(self, res, GL_ACTIVE_UNIFORMS, &numUniforms); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 4549 | ctx->m_shared->initShaderProgramData(res, numUniforms); |
| 4550 | |
| 4551 | GLint maxLength=0; |
| 4552 | ctx->glGetProgramiv(self, res, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength); |
| 4553 | |
| 4554 | GLint size; GLenum uniformType; GLchar* name = new GLchar[maxLength + 1]; |
| 4555 | |
| 4556 | for (GLint i = 0; i < numUniforms; ++i) { |
| 4557 | ctx->glGetActiveUniform(self, res, i, maxLength, NULL, &size, &uniformType, name); |
| 4558 | GLint location = ctx->m_glGetUniformLocation_enc(self, res, name); |
| 4559 | ctx->m_shared->setShaderProgramIndexInfo(res, i, location, size, uniformType, name); |
| 4560 | } |
| 4561 | |
| 4562 | ctx->m_shared->setupShaderProgramLocationShiftWAR(res); |
| 4563 | |
| 4564 | delete [] name; |
| 4565 | |
| 4566 | return res; |
| 4567 | } |
| 4568 | |
| 4569 | void GL2Encoder::s_glProgramUniform1f(void* self, GLuint program, GLint location, GLfloat v0) |
| 4570 | { |
| 4571 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4572 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location); |
| 4573 | ctx->m_glProgramUniform1f_enc(self, program, hostLoc, v0); |
| 4574 | } |
| 4575 | |
| 4576 | void GL2Encoder::s_glProgramUniform1fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value) |
| 4577 | { |
| 4578 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4579 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location); |
| 4580 | ctx->m_glProgramUniform1fv_enc(self, program, hostLoc, count, value); |
| 4581 | } |
| 4582 | |
| 4583 | void GL2Encoder::s_glProgramUniform1i(void* self, GLuint program, GLint location, GLint v0) |
| 4584 | { |
| 4585 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4586 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location); |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 4587 | ctx->m_glProgramUniform1i_enc(self, program, hostLoc, v0); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 4588 | |
| 4589 | GLClientState* state = ctx->m_state; |
| 4590 | GLSharedGroupPtr shared = ctx->m_shared; |
| 4591 | GLenum target; |
| 4592 | |
| 4593 | if (shared->setSamplerUniform(program, location, v0, &target)) { |
| 4594 | GLenum origActiveTexture = state->getActiveTextureUnit(); |
| 4595 | if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + v0, target)) { |
| 4596 | ctx->m_glActiveTexture_enc(self, origActiveTexture); |
| 4597 | } |
| 4598 | state->setActiveTextureUnit(origActiveTexture); |
| 4599 | } |
| 4600 | } |
| 4601 | |
| 4602 | void GL2Encoder::s_glProgramUniform1iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value) |
| 4603 | { |
| 4604 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4605 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location); |
| 4606 | ctx->m_glProgramUniform1iv_enc(self, program, hostLoc, count, value); |
| 4607 | } |
| 4608 | |
| 4609 | void GL2Encoder::s_glProgramUniform1ui(void* self, GLuint program, GLint location, GLuint v0) |
| 4610 | { |
| 4611 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4612 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location); |
| 4613 | ctx->m_glProgramUniform1ui_enc(self, program, hostLoc, v0); |
| 4614 | |
| 4615 | GLClientState* state = ctx->m_state; |
| 4616 | GLSharedGroupPtr shared = ctx->m_shared; |
| 4617 | GLenum target; |
| 4618 | |
| 4619 | if (shared->setSamplerUniform(program, location, v0, &target)) { |
| 4620 | GLenum origActiveTexture = state->getActiveTextureUnit(); |
| 4621 | if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + v0, target)) { |
| 4622 | ctx->m_glActiveTexture_enc(self, origActiveTexture); |
| 4623 | } |
| 4624 | state->setActiveTextureUnit(origActiveTexture); |
| 4625 | } |
| 4626 | } |
| 4627 | |
| 4628 | void GL2Encoder::s_glProgramUniform1uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value) |
| 4629 | { |
| 4630 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4631 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location); |
| 4632 | ctx->m_glProgramUniform1uiv_enc(self, program, hostLoc, count, value); |
| 4633 | } |
| 4634 | |
| 4635 | void GL2Encoder::s_glProgramUniform2f(void* self, GLuint program, GLint location, GLfloat v0, GLfloat v1) |
| 4636 | { |
| 4637 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4638 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location); |
| 4639 | ctx->m_glProgramUniform2f_enc(self, program, hostLoc, v0, v1); |
| 4640 | } |
| 4641 | |
| 4642 | void GL2Encoder::s_glProgramUniform2fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value) |
| 4643 | { |
| 4644 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4645 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location); |
| 4646 | ctx->m_glProgramUniform2fv_enc(self, program, hostLoc, count, value); |
| 4647 | } |
| 4648 | |
| 4649 | void GL2Encoder::s_glProgramUniform2i(void* self, GLuint program, GLint location, GLint v0, GLint v1) |
| 4650 | { |
| 4651 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4652 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location); |
| 4653 | ctx->m_glProgramUniform2i_enc(self, program, hostLoc, v0, v1); |
| 4654 | } |
| 4655 | |
| 4656 | void GL2Encoder::s_glProgramUniform2iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value) |
| 4657 | { |
| 4658 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4659 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location); |
| 4660 | ctx->m_glProgramUniform2iv_enc(self, program, hostLoc, count, value); |
| 4661 | } |
| 4662 | |
| 4663 | void GL2Encoder::s_glProgramUniform2ui(void* self, GLuint program, GLint location, GLint v0, GLuint v1) |
| 4664 | { |
| 4665 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4666 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location); |
| 4667 | ctx->m_glProgramUniform2ui_enc(self, program, hostLoc, v0, v1); |
| 4668 | } |
| 4669 | |
| 4670 | void GL2Encoder::s_glProgramUniform2uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value) |
| 4671 | { |
| 4672 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4673 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location); |
| 4674 | ctx->m_glProgramUniform2uiv_enc(self, program, hostLoc, count, value); |
| 4675 | } |
| 4676 | |
| 4677 | void GL2Encoder::s_glProgramUniform3f(void* self, GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2) |
| 4678 | { |
| 4679 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4680 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location); |
| 4681 | ctx->m_glProgramUniform3f_enc(self, program, hostLoc, v0, v1, v2); |
| 4682 | } |
| 4683 | |
| 4684 | void GL2Encoder::s_glProgramUniform3fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value) |
| 4685 | { |
| 4686 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4687 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location); |
| 4688 | ctx->m_glProgramUniform3fv_enc(self, program, hostLoc, count, value); |
| 4689 | } |
| 4690 | |
| 4691 | void GL2Encoder::s_glProgramUniform3i(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLint v2) |
| 4692 | { |
| 4693 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4694 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location); |
| 4695 | ctx->m_glProgramUniform3i_enc(self, program, hostLoc, v0, v1, v2); |
| 4696 | } |
| 4697 | |
| 4698 | void GL2Encoder::s_glProgramUniform3iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value) |
| 4699 | { |
| 4700 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4701 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location); |
| 4702 | ctx->m_glProgramUniform3iv_enc(self, program, hostLoc, count, value); |
| 4703 | } |
| 4704 | |
| 4705 | void GL2Encoder::s_glProgramUniform3ui(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLuint v2) |
| 4706 | { |
| 4707 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4708 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location); |
| 4709 | ctx->m_glProgramUniform3ui_enc(self, program, hostLoc, v0, v1, v2); |
| 4710 | } |
| 4711 | |
| 4712 | void GL2Encoder::s_glProgramUniform3uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value) |
| 4713 | { |
| 4714 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4715 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location); |
| 4716 | ctx->m_glProgramUniform3uiv_enc(self, program, hostLoc, count, value); |
| 4717 | } |
| 4718 | |
| 4719 | void GL2Encoder::s_glProgramUniform4f(void* self, GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) |
| 4720 | { |
| 4721 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4722 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location); |
| 4723 | ctx->m_glProgramUniform4f_enc(self, program, hostLoc, v0, v1, v2, v3); |
| 4724 | } |
| 4725 | |
| 4726 | void GL2Encoder::s_glProgramUniform4fv(void* self, GLuint program, GLint location, GLsizei count, const GLfloat *value) |
| 4727 | { |
| 4728 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4729 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location); |
| 4730 | ctx->m_glProgramUniform4fv_enc(self, program, hostLoc, count, value); |
| 4731 | } |
| 4732 | |
| 4733 | void GL2Encoder::s_glProgramUniform4i(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3) |
| 4734 | { |
| 4735 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4736 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location); |
| 4737 | ctx->m_glProgramUniform4i_enc(self, program, hostLoc, v0, v1, v2, v3); |
| 4738 | } |
| 4739 | |
| 4740 | void GL2Encoder::s_glProgramUniform4iv(void* self, GLuint program, GLint location, GLsizei count, const GLint *value) |
| 4741 | { |
| 4742 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4743 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location); |
| 4744 | ctx->m_glProgramUniform4iv_enc(self, program, hostLoc, count, value); |
| 4745 | } |
| 4746 | |
| 4747 | void GL2Encoder::s_glProgramUniform4ui(void* self, GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLuint v3) |
| 4748 | { |
| 4749 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4750 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location); |
| 4751 | ctx->m_glProgramUniform4ui_enc(self, program, hostLoc, v0, v1, v2, v3); |
| 4752 | } |
| 4753 | |
| 4754 | void GL2Encoder::s_glProgramUniform4uiv(void* self, GLuint program, GLint location, GLsizei count, const GLuint *value) |
| 4755 | { |
| 4756 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4757 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location); |
| 4758 | ctx->m_glProgramUniform4uiv_enc(self, program, hostLoc, count, value); |
| 4759 | } |
| 4760 | |
| 4761 | void GL2Encoder::s_glProgramUniformMatrix2fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) |
| 4762 | { |
| 4763 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4764 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location); |
| 4765 | ctx->m_glProgramUniformMatrix2fv_enc(self, program, hostLoc, count, transpose, value); |
| 4766 | } |
| 4767 | |
| 4768 | void GL2Encoder::s_glProgramUniformMatrix2x3fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) |
| 4769 | { |
| 4770 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4771 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location); |
| 4772 | ctx->m_glProgramUniformMatrix2x3fv_enc(self, program, hostLoc, count, transpose, value); |
| 4773 | } |
| 4774 | |
| 4775 | void GL2Encoder::s_glProgramUniformMatrix2x4fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) |
| 4776 | { |
| 4777 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4778 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location); |
| 4779 | ctx->m_glProgramUniformMatrix2x4fv_enc(self, program, hostLoc, count, transpose, value); |
| 4780 | } |
| 4781 | |
| 4782 | void GL2Encoder::s_glProgramUniformMatrix3fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) |
| 4783 | { |
| 4784 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4785 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location); |
| 4786 | ctx->m_glProgramUniformMatrix3fv_enc(self, program, hostLoc, count, transpose, value); |
| 4787 | } |
| 4788 | |
| 4789 | void GL2Encoder::s_glProgramUniformMatrix3x2fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) |
| 4790 | { |
| 4791 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4792 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location); |
| 4793 | ctx->m_glProgramUniformMatrix3x2fv_enc(self, program, hostLoc, count, transpose, value); |
| 4794 | } |
| 4795 | |
| 4796 | void GL2Encoder::s_glProgramUniformMatrix3x4fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) |
| 4797 | { |
| 4798 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4799 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location); |
| 4800 | ctx->m_glProgramUniformMatrix3x4fv_enc(self, program, hostLoc, count, transpose, value); |
| 4801 | } |
| 4802 | |
| 4803 | void GL2Encoder::s_glProgramUniformMatrix4fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) |
| 4804 | { |
| 4805 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4806 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location); |
| 4807 | ctx->m_glProgramUniformMatrix4fv_enc(self, program, hostLoc, count, transpose, value); |
| 4808 | } |
| 4809 | |
| 4810 | void GL2Encoder::s_glProgramUniformMatrix4x2fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) |
| 4811 | { |
| 4812 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4813 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location); |
| 4814 | ctx->m_glProgramUniformMatrix4x2fv_enc(self, program, hostLoc, count, transpose, value); |
| 4815 | } |
| 4816 | |
| 4817 | void GL2Encoder::s_glProgramUniformMatrix4x3fv(void* self, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) |
| 4818 | { |
| 4819 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4820 | GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location); |
| 4821 | ctx->m_glProgramUniformMatrix4x3fv_enc(self, program, hostLoc, count, transpose, value); |
| 4822 | } |
| 4823 | |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 4824 | void GL2Encoder::s_glProgramParameteri(void* self, GLuint program, GLenum pname, GLint value) { |
| 4825 | GL2Encoder* ctx = (GL2Encoder*)self; |
| 4826 | ctx->m_glProgramParameteri_enc(self, program, pname, value); |
| 4827 | } |
| 4828 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 4829 | void GL2Encoder::s_glUseProgramStages(void *self, GLuint pipeline, GLbitfield stages, GLuint program) |
| 4830 | { |
| 4831 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4832 | GLClientState* state = ctx->m_state; |
| 4833 | GLSharedGroupPtr shared = ctx->m_shared; |
| 4834 | |
| 4835 | SET_ERROR_IF(!pipeline, GL_INVALID_OPERATION); |
| 4836 | SET_ERROR_IF(program && !shared->isShaderOrProgramObject(program), GL_INVALID_VALUE); |
| 4837 | SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION); |
| 4838 | |
| 4839 | ctx->m_glUseProgramStages_enc(self, pipeline, stages, program); |
| 4840 | state->associateProgramWithPipeline(program, pipeline); |
| 4841 | |
| 4842 | // There is an active non-separable shader program in effect; no need to update external/2D bindings. |
| 4843 | if (state->currentProgram()) { |
| 4844 | return; |
| 4845 | } |
| 4846 | |
| 4847 | // Otherwise, update host texture 2D bindings. |
| 4848 | ctx->updateHostTexture2DBindingsFromProgramData(program); |
| 4849 | } |
| 4850 | |
| 4851 | void GL2Encoder::s_glBindProgramPipeline(void* self, GLuint pipeline) |
| 4852 | { |
| 4853 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4854 | GLClientState* state = ctx->m_state; |
| 4855 | |
| 4856 | ctx->m_glBindProgramPipeline_enc(self, pipeline); |
| 4857 | |
| 4858 | // There is an active non-separable shader program in effect; no need to update external/2D bindings. |
| 4859 | if (!pipeline || state->currentProgram()) { |
| 4860 | return; |
| 4861 | } |
| 4862 | |
| 4863 | GLClientState::ProgramPipelineIterator it = state->programPipelineBegin(); |
| 4864 | for (; it != state->programPipelineEnd(); ++it) { |
| 4865 | if (it->second == pipeline) { |
| 4866 | ctx->updateHostTexture2DBindingsFromProgramData(it->first); |
| 4867 | } |
| 4868 | } |
| 4869 | } |
| 4870 | |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 4871 | void GL2Encoder::s_glGetProgramResourceiv(void* self, GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum * props, GLsizei bufSize, GLsizei * length, GLint * params) { |
| 4872 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4873 | SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE); |
| 4874 | if (bufSize == 0) { |
| 4875 | if (length) *length = 0; |
| 4876 | return; |
| 4877 | } |
| 4878 | |
| 4879 | // Avoid modifying |name| if |*length| < bufSize. |
| 4880 | GLint* intermediate = new GLint[bufSize]; |
| 4881 | GLsizei* myLength = length ? length : new GLsizei; |
| 4882 | bool needFreeLength = length == NULL; |
| 4883 | |
| 4884 | ctx->m_glGetProgramResourceiv_enc(self, program, programInterface, index, propCount, props, bufSize, myLength, intermediate); |
| 4885 | GLsizei writtenInts = *myLength; |
| 4886 | memcpy(params, intermediate, writtenInts * sizeof(GLint)); |
| 4887 | |
| 4888 | delete [] intermediate; |
| 4889 | if (needFreeLength) |
| 4890 | delete myLength; |
| 4891 | } |
| 4892 | |
| 4893 | GLuint GL2Encoder::s_glGetProgramResourceIndex(void* self, GLuint program, GLenum programInterface, const char* name) { |
| 4894 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4895 | return ctx->m_glGetProgramResourceIndex_enc(self, program, programInterface, name); |
| 4896 | } |
| 4897 | |
| 4898 | GLint GL2Encoder::s_glGetProgramResourceLocation(void* self, GLuint program, GLenum programInterface, const char* name) { |
| 4899 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4900 | return ctx->m_glGetProgramResourceLocation_enc(self, program, programInterface, name); |
| 4901 | } |
| 4902 | |
| 4903 | void GL2Encoder::s_glGetProgramResourceName(void* self, GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei* length, char* name) { |
| 4904 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4905 | SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE); |
| 4906 | if (bufSize == 0) { |
| 4907 | if (length) *length = 0; |
| 4908 | return; |
| 4909 | } |
| 4910 | |
| 4911 | // Avoid modifying |name| if |*length| < bufSize. |
| 4912 | char* intermediate = new char[bufSize]; |
| 4913 | GLsizei* myLength = length ? length : new GLsizei; |
| 4914 | bool needFreeLength = length == NULL; |
| 4915 | |
| 4916 | ctx->m_glGetProgramResourceName_enc(self, program, programInterface, index, bufSize, myLength, intermediate); |
| 4917 | GLsizei writtenStrLen = *myLength; |
| 4918 | memcpy(name, intermediate, writtenStrLen + 1); |
| 4919 | |
| 4920 | delete [] intermediate; |
| 4921 | if (needFreeLength) |
| 4922 | delete myLength; |
| 4923 | } |
| 4924 | |
| 4925 | void GL2Encoder::s_glGetProgramPipelineInfoLog(void* self, GLuint pipeline, GLsizei bufSize, GLsizei* length, GLchar* infoLog) { |
| 4926 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4927 | SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE); |
| 4928 | if (bufSize == 0) { |
| 4929 | if (length) *length = 0; |
| 4930 | return; |
| 4931 | } |
| 4932 | |
| 4933 | // Avoid modifying |infoLog| if |*length| < bufSize. |
| 4934 | GLchar* intermediate = new GLchar[bufSize]; |
| 4935 | GLsizei* myLength = length ? length : new GLsizei; |
| 4936 | bool needFreeLength = length == NULL; |
| 4937 | |
| 4938 | ctx->m_glGetProgramPipelineInfoLog_enc(self, pipeline, bufSize, myLength, intermediate); |
| 4939 | GLsizei writtenStrLen = *myLength; |
| 4940 | memcpy(infoLog, intermediate, writtenStrLen + 1); |
| 4941 | |
| 4942 | delete [] intermediate; |
| 4943 | if (needFreeLength) |
| 4944 | delete myLength; |
| 4945 | } |
| 4946 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 4947 | void GL2Encoder::s_glVertexAttribFormat(void* self, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset) { |
| 4948 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4949 | GLClientState* state = ctx->m_state; |
| 4950 | |
Lingfeng Yang | 0728990 | 2017-01-27 12:26:19 -0800 | [diff] [blame] | 4951 | VALIDATE_VERTEX_ATTRIB_INDEX(attribindex); |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 4952 | SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION); |
| 4953 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 4954 | state->setVertexAttribFormat(attribindex, size, type, normalized, relativeoffset, false); |
| 4955 | ctx->m_glVertexAttribFormat_enc(ctx, attribindex, size, type, normalized, relativeoffset); |
| 4956 | } |
| 4957 | |
| 4958 | void GL2Encoder::s_glVertexAttribIFormat(void* self, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset) { |
| 4959 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4960 | GLClientState* state = ctx->m_state; |
| 4961 | |
Lingfeng Yang | 0728990 | 2017-01-27 12:26:19 -0800 | [diff] [blame] | 4962 | VALIDATE_VERTEX_ATTRIB_INDEX(attribindex); |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 4963 | SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION); |
| 4964 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 4965 | state->setVertexAttribFormat(attribindex, size, type, GL_FALSE, relativeoffset, true); |
| 4966 | ctx->m_glVertexAttribIFormat_enc(ctx, attribindex, size, type, relativeoffset); |
| 4967 | } |
| 4968 | |
| 4969 | void GL2Encoder::s_glVertexBindingDivisor(void* self, GLuint bindingindex, GLuint divisor) { |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 4970 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4971 | GLClientState* state = ctx->m_state; |
| 4972 | |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 4973 | SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION); |
| 4974 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 4975 | state->setVertexBindingDivisor(bindingindex, divisor); |
| 4976 | ctx->m_glVertexBindingDivisor_enc(ctx, bindingindex, divisor); |
| 4977 | } |
| 4978 | |
| 4979 | void GL2Encoder::s_glVertexAttribBinding(void* self, GLuint attribindex, GLuint bindingindex) { |
| 4980 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4981 | GLClientState* state = ctx->m_state; |
Lingfeng Yang | 0728990 | 2017-01-27 12:26:19 -0800 | [diff] [blame] | 4982 | VALIDATE_VERTEX_ATTRIB_INDEX(attribindex); |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 4983 | SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 4984 | |
| 4985 | state->setVertexAttribBinding(attribindex, bindingindex); |
| 4986 | ctx->m_glVertexAttribBinding_enc(ctx, attribindex, bindingindex); |
| 4987 | } |
| 4988 | |
| 4989 | void GL2Encoder::s_glBindVertexBuffer(void* self, GLuint bindingindex, GLuint buffer, GLintptr offset, GLintptr stride) { |
| 4990 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 4991 | GLClientState* state = ctx->m_state; |
| 4992 | |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 4993 | SET_ERROR_IF(offset < 0, GL_INVALID_VALUE); |
| 4994 | |
| 4995 | GLint maxStride; |
| 4996 | ctx->glGetIntegerv(ctx, GL_MAX_VERTEX_ATTRIB_STRIDE, &maxStride); |
| 4997 | SET_ERROR_IF(stride < 0 || stride > maxStride, GL_INVALID_VALUE); |
| 4998 | |
| 4999 | SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION); |
| 5000 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 5001 | state->bindIndexedBuffer(0, bindingindex, buffer, offset, 0, stride, stride); |
| 5002 | ctx->m_glBindVertexBuffer_enc(ctx, bindingindex, buffer, offset, stride); |
| 5003 | } |
| 5004 | |
| 5005 | void GL2Encoder::s_glDrawArraysIndirect(void* self, GLenum mode, const void* indirect) { |
| 5006 | GL2Encoder *ctx = (GL2Encoder*)self; |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 5007 | GLClientState* state = ctx->m_state; |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 5008 | |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 5009 | bool hasClientArrays = false; |
| 5010 | ctx->getVBOUsage(&hasClientArrays, NULL); |
| 5011 | |
| 5012 | SET_ERROR_IF(hasClientArrays, GL_INVALID_OPERATION); |
| 5013 | SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION); |
| 5014 | SET_ERROR_IF(!ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER), GL_INVALID_OPERATION); |
| 5015 | |
| 5016 | GLuint indirectStructSize = glUtilsIndirectStructSize(INDIRECT_COMMAND_DRAWARRAYS); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 5017 | if (ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER)) { |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 5018 | // BufferData* buf = ctx->getBufferData(target); |
| 5019 | // if (buf) { |
| 5020 | // SET_ERROR_IF((GLuint)(uintptr_t)indirect + indirectStructSize > buf->m_size, GL_INVALID_VALUE); |
| 5021 | // } |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 5022 | ctx->glDrawArraysIndirectOffsetAEMU(ctx, mode, (uintptr_t)indirect); |
| 5023 | } else { |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 5024 | // Client command structs are technically allowed in desktop OpenGL, but not in ES. |
| 5025 | // This is purely for debug/dev purposes. |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 5026 | ctx->glDrawArraysIndirectDataAEMU(ctx, mode, indirect, indirectStructSize); |
| 5027 | } |
| 5028 | } |
| 5029 | |
| 5030 | void GL2Encoder::s_glDrawElementsIndirect(void* self, GLenum mode, GLenum type, const void* indirect) { |
| 5031 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 5032 | |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 5033 | GLClientState* state = ctx->m_state; |
| 5034 | |
| 5035 | bool hasClientArrays = false; |
| 5036 | ctx->getVBOUsage(&hasClientArrays, NULL); |
| 5037 | |
| 5038 | SET_ERROR_IF(hasClientArrays, GL_INVALID_OPERATION); |
| 5039 | SET_ERROR_IF(!state->currentVertexArrayObject(), GL_INVALID_OPERATION); |
| 5040 | SET_ERROR_IF(!ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER), GL_INVALID_OPERATION); |
| 5041 | |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 5042 | SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION); |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 5043 | |
| 5044 | GLuint indirectStructSize = glUtilsIndirectStructSize(INDIRECT_COMMAND_DRAWELEMENTS); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 5045 | if (ctx->boundBuffer(GL_DRAW_INDIRECT_BUFFER)) { |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 5046 | // BufferData* buf = ctx->getBufferData(target); |
| 5047 | // if (buf) { |
| 5048 | // SET_ERROR_IF((GLuint)(uintptr_t)indirect + indirectStructSize > buf->m_size, GL_INVALID_VALUE); |
| 5049 | // } |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 5050 | ctx->glDrawElementsIndirectOffsetAEMU(ctx, mode, type, (uintptr_t)indirect); |
| 5051 | } else { |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 5052 | // Client command structs are technically allowed in desktop OpenGL, but not in ES. |
| 5053 | // This is purely for debug/dev purposes. |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 5054 | ctx->glDrawElementsIndirectDataAEMU(ctx, mode, type, indirect, indirectStructSize); |
| 5055 | } |
| 5056 | |
| 5057 | } |
| 5058 | |
| 5059 | void GL2Encoder::s_glTexStorage2DMultisample(void* self, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) { |
| 5060 | GL2Encoder *ctx = (GL2Encoder*)self; |
| 5061 | GLClientState* state = ctx->m_state; |
| 5062 | |
| 5063 | SET_ERROR_IF(target != GL_TEXTURE_2D_MULTISAMPLE, GL_INVALID_ENUM); |
| 5064 | SET_ERROR_IF(!GLESv2Validation::pixelInternalFormat(internalformat), GL_INVALID_ENUM); |
| 5065 | SET_ERROR_IF(!state->getBoundTexture(target), GL_INVALID_OPERATION); |
| 5066 | SET_ERROR_IF(width < 1 || height < 1, GL_INVALID_VALUE); |
| 5067 | SET_ERROR_IF(state->isBoundTextureImmutableFormat(target), GL_INVALID_OPERATION); |
Lingfeng Yang | d3ae106 | 2017-01-18 11:42:04 -0800 | [diff] [blame] | 5068 | GLint max_samples; |
| 5069 | ctx->s_glGetInternalformativ(ctx, target, internalformat, GL_SAMPLES, 1, &max_samples); |
| 5070 | SET_ERROR_IF(samples > max_samples, GL_INVALID_OPERATION); |
Lingfeng Yang | 46153ab | 2017-01-09 13:37:22 -0800 | [diff] [blame] | 5071 | |
| 5072 | state->setBoundTextureInternalFormat(target, internalformat); |
| 5073 | state->setBoundTextureDims(target, 0, width, height, 1); |
| 5074 | state->setBoundTextureImmutableFormat(target); |
| 5075 | state->setBoundTextureSamples(target, samples); |
| 5076 | |
| 5077 | ctx->m_glTexStorage2DMultisample_enc(ctx, target, samples, internalformat, width, height, fixedsamplelocations); |
| 5078 | } |
| 5079 | |